package com.siecom.module;

import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;

import com.ivsign.android.IDCReader.IDCReadInterface;
import com.pos.emvcore.EmvCore;
import com.pos.emvcore.beans.AidList;
import com.pos.emvcore.beans.AppList;
import com.pos.emvcore.beans.CAPubKey;
import com.siecom.bean.LoadLogBean;
import com.siecom.constconfig.ConstDefine;
import com.siecom.constconfig.ConstTags;
import com.siecom.constconfig.ErrorDefine;
import com.siecom.bean.BankCardInfoBean;
import com.siecom.bean.TradeLogBean;
import com.siecom.hostservice.MainActivity;
import com.siecom.tool.ByteTool;
import com.siecom.tool.LogUtil;
import com.siecom.tool.StringUtil;
import com.siecom.tool.Timer;
import com.siecom.zhq.hostservice.BuildConfig;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;


public class FinancialRunnable extends ModuleRunnable {

    public static final String TAG = FinancialRunnable.class.getSimpleName();
    public static FinancialModule financialModule = FinancialModule.getInstance();

    private EmvCore mEmvCore = null;

    public enum Action {

        READ_MSR,
        READ_IC_CARD_NO,
        READ_PIC_CARD_NO,
        AUTO_READ_CARD_NO,
        READ_IC_INFO,
        READ_PIC_INFO,
        AUTO_READ_CARD_INFO,
        READ_PIC_LOG,
        READ_IC_LOG,
        READ_PIC_LOAD,
        READ_IC_LOAD,
        AUTO_READ_LOAD,
        AUTO_READ_LOG,
        ARPCANDSCRIPT,
        IC_POWER_ON,
        IC_APDU,
        IC_POWER_OFF,
        READ_SOCIAL_CARD, //社保卡

        AUTO_READ_CHECK_CARD, //自动检测卡类型
    }

    private Action type;
    private EmvOptions emvOptions;

    private int cardType;
    private String ARPC;
    private String ScriptStr;
    private static int mCardCheckedType = -1;

    private String[] wantTags = null;

    private String inJsonStr;

    public void stopRun() {
        this.runFlag = false;
        financialModule.setStopRun(true);
    }

    public FinancialRunnable(Action type, EmvOptions emvOptions, final DeviceCallback callback, final String[] wantTags, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
        this.emvOptions = emvOptions;
        this.wantTags = wantTags;
        this.mEmvCore = MainActivity.getEmvCore();
    }


    public FinancialRunnable(Action type, EmvOptions emvOptions, final DeviceCallback callback, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
        this.emvOptions = emvOptions;

        this.mEmvCore = MainActivity.getEmvCore();
    }

    public FinancialRunnable(Action type,int cardType, String ARPC, String ScriptStr, final DeviceCallback callback, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
        this.cardType = cardType;
        this.ARPC = ARPC;
        this.ScriptStr = ScriptStr;
        this.mEmvCore = MainActivity.getEmvCore();
    }

    /**
     * 读社保卡
     * @param type 类型 读社保卡
     * @param cardType 卡类型 自动区分或者只支持插卡
     * @param inJsonStr 传入的json 参数
     * @param callback 回调
     * @param timeOutMs 超时时间
     * @param isOnMain 是否主线程
     */
    public FinancialRunnable(Action type,int cardType, String inJsonStr, final DeviceCallback callback, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
        this.cardType = cardType;
        this.inJsonStr = inJsonStr; //
        this.mEmvCore = MainActivity.getEmvCore();
    }

    @Override
    public void run() {
        synchronized (this) {
//            financialModule.flush();
//            initEmv();
            switch (type) {
                case READ_MSR:
                    readMsr();
                    break;
                case READ_IC_CARD_NO:
                    break;
                case READ_PIC_CARD_NO:

                    readPiccCardNo();
                    break;
                case AUTO_READ_CARD_NO:
                    autoReadCardNo();
                    break;

                case READ_IC_INFO:
                    readIcCardInfo();
                    break;

                case READ_PIC_INFO:
                    readPiccInfo();
                    break;

                case READ_IC_LOG:
                    readIcLog();
                    break;
                case READ_PIC_LOG:
                    readPicLog();
                    break;
                case AUTO_READ_LOG:
                    autoReadCardLog();
                    break;


                case READ_IC_LOAD:
                    readIcLoadLog();
                    break;

                case READ_PIC_LOAD:
                    readPicLoadLog();
                    break;


                case AUTO_READ_CARD_INFO:
                    autoReadCardInfo();
                    break;
                case AUTO_READ_CHECK_CARD:
                    autoReadCheckCard();
                    break;
                case AUTO_READ_LOAD:
                    autoReadCardLoad();
                    break;

                case ARPCANDSCRIPT:
//                    ARPCExecuteScript(cardType, ARPC, ScriptStr);
                    ARPCExecuteScript2(cardType,0,0);
                    break;

                case IC_POWER_ON:
                    icCardPowerOn();
                    break;
                case IC_APDU:
                    icCardApdu();
                    break;
                case IC_POWER_OFF:
                    closeModule();
                    break;

                case READ_SOCIAL_CARD:
                    readSocialCard();
                    break;
            }
            isFinish = true;
            Log.e(TAG, "COMPLETED---");
        }
    }



    public int initEmv() {

        if (financialModule.EmvLib_Init() == 0) {
            Log.e("EmvLib_Init", "ok");
            return 0;
        }
        return -1;
    }

    public int ARPCExecuteScript(int ICType, String ARPC, String ScriptStr) {

        byte[] RspCode = null;
        byte[] AuthCode = "123456".getBytes();
        int AuthCodeLen = 0;
        byte ucResult = 0;
        byte[] IAuthData = new byte[8];
        byte[] Script = null;
        int IAuthDataLen = 0;
        int ScriptLen = 0;
        byte[] Result = new byte[1024];
        int[] RetLen = new int[1];
        int ret = -1;
//        final String arpc = "910A2501EEC5A3FDBF563030";//91开头，脚本是72开头
//        final String script = "7251860F04DA9F790A000000000000A4B17D6D860F04DA9F770A0000001000008C09E6BF862D04DC010C2870229F61123433313232313139383830373136313231589F6201105F2006C5CBB0D8D3EEA168BB5A";

        try {
            int nIndex = ARPC.indexOf("91");
            if (nIndex != -1) {
                String substr = ARPC.substring(nIndex + 2,
                        nIndex + 4);
                IAuthDataLen = Integer.parseInt(substr, 16);
                Log.e(TAG, "IAuthDataLen = " + IAuthDataLen);
                IAuthData = StringUtil.hexStringToBytes(ARPC.substring(nIndex + 4, nIndex + 4 + IAuthDataLen * 2));
                Log.e(TAG, "IAuthData = " + ByteTool.bytearrayToHexString(IAuthData, IAuthDataLen));
                RspCode = StringUtil.hexStringToBytes(ARPC.substring(nIndex + 4 + IAuthDataLen * 2 - 4, nIndex + 4 + IAuthDataLen * 2));
                Log.e(TAG, "RspCode = " + ByteTool.bytearrayToHexString(RspCode, 2));
            }
            nIndex = ScriptStr.indexOf("72");
            if (nIndex != -1) {
                String substr = ScriptStr.substring(nIndex + 2,
                        nIndex + 4);
                ScriptLen = Integer.parseInt(substr, 16) + 2;
                Log.e(TAG, "ScriptLen = " + ScriptLen);
                Script = StringUtil.hexStringToBytes(ScriptStr.substring(nIndex, nIndex + ScriptLen * 2));
                Log.e(TAG, "Script = " + ByteTool.bytearrayToHexString(Script, ScriptLen));
            } else {
                Script = new byte[0];
            }
            if (ICType == 0x00)
                ret = financialModule.EmvLib_ProcTransComplete(ucResult, RspCode, AuthCode, AuthCodeLen, IAuthData, IAuthDataLen, Script, ScriptLen);
            else if (ICType == 0x02)
                ret = financialModule.EmvLib_ProcCLTransComplete((byte) 0, RspCode, AuthCode, AuthCodeLen);
            else {
                deliverError(ErrorDefine.CARD_TYPE_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.CARD_TYPE_ERR));
                return ret;
            }
            if (ret != 0) {
                Log.e(TAG, "EmvLib_ProcCLTransComplete/EmvLib_ProcTransComplete: ret = " + ret);
                deliverError(ErrorDefine.PBOC_COMPLETE, ErrorDefine.getErrorDescribe(ErrorDefine.PBOC_COMPLETE));
                return ret;
            }
            byte[] ScriptResult = new byte[0];
            if(nIndex!=-1) {
                if (ICType == 0x00) {
                    ret = financialModule.EmvLib_GetScriptResult(Result, RetLen);
                    if (ret != 0) {
                        Log.e(TAG, "EmvLib_GetScriptResult: ret = " + ret);
                        deliverError(ErrorDefine.GET_SCRIPT_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_SCRIPT_ERR));
                        return ret;
                    }
                }
                ScriptResult = new byte[RetLen[0]];

                System.arraycopy(Result, 0, ScriptResult, 0, ScriptResult.length);
            }
            String[] tags = {"9F26"}; //应用密文（AC）  长度8

            byte[] dataOut = new byte[1024];
            int[] len1 = new int[1];
            ret = financialModule.EmvLib_GetTags(tags, dataOut, len1);

            byte[] out = new byte[len1[0]];
            System.arraycopy(dataOut, 0, out, 0, len1[0]);
            if (ret == 0) {
                Bundle bundle = new Bundle();
                bundle.putInt("result", ret);
                bundle.putString("ScriptResult", ByteTool.byte2hex(ScriptResult));
                bundle.putString("TC", ByteTool.byte2hex(out));
                deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            } else {
                Bundle bundle = new Bundle();
                bundle.putInt("code", ret);
                bundle.putString("ScriptResult", ByteTool.byte2hex(ScriptResult));
                bundle.putString("TC", ByteTool.byte2hex(out));
                bundle.putString("message", "unknow script or arpc err");
                deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            }
        } catch (Exception e) {
            e.printStackTrace();
            deliverError(e.hashCode(), e.getMessage());

        } finally {
            if (ICType == 0x00)
                financialModule.libIccClose((byte) 0x00);
            else if (ICType == 0x02)
                financialModule.libPiccClose();

            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }
        return ret;

    }

    /**
     * 发卡行数据认证 内部认证 校验ARPC
     * @param arpc ARPC
     * @return
     */
    public int externalAuth(String arpc){
        byte command[] = {0x00,(byte) 0x82,0x00,0x00};
        if (arpc.startsWith("910A")){
            arpc = arpc.substring(4);
        }
        LogUtil.e(TAG,"arpc indata == " + arpc);
        byte dataIn[] = ByteTool.hexStr2Bytes(arpc);
        String outStr = apduRead(command,dataIn,0xff);
        LogUtil.e(TAG,"externalAuth == " + outStr);

        return 0;
    }

    /**
     * 传入脚本给银行卡去执行
     * @param script 脚本 一般以71 或 72开头
     */
    public String executeScript(String script){
        byte[] scriptBuf = ByteTool.hexStr2Bytes(script);
        String outStr = "";
        if (!script.startsWith("71") && !script.startsWith("72"))
            return "";
        int index = script.indexOf("86");
        if (index < 0) return "";
        List<String> orderList = new ArrayList<>();
//        String[] orders = script.split("86");
        //72189F180400000001 86 0F04DA9F790A000000018600E27C595B
        //先把86前面的截取掉
        script = script.substring(index);

        while (script.length() > 0){
            if (script.startsWith("86")){
                int len = Integer.parseInt(script.substring(2, 4), 16);
                LogUtil.e(TAG,"len == " + len);
                String order = script.substring(2,len*2 + 4);
                LogUtil.e(TAG,"order == " + order);
                orderList.add(order);
                script = script.substring(len*2 + 4);
                LogUtil.e(TAG,"script == " + script);
            }else {
                break;
            }

        }

        LogUtil.e(TAG, "orderList len == " + orderList.size());
        for (String order : orderList) {
            LogUtil.e(TAG, "order == " + order);
            int len = Integer.parseInt(order.substring(0, 2), 16);
            LogUtil.e(TAG, "len == " + len);
            if (len < 8 || len * 2 + 2 != order.length()  )
                continue;

            String command = order.substring(2, 10);

            LogUtil.e(TAG, "command == " + command);
            String dataInStr = "";
            if (order.length() >= 12) {
                int dataInLen = Integer.parseInt(order.substring(10, 12),16);
                dataInStr = order.substring(12, dataInLen*2 + 12);
                LogUtil.e(TAG, "dataInStr == " + dataInStr);
            }


            if (mCardCheckedType == ConstDefine.IC_CARD){
                int ret = mEmvCore.EmvLibScriptProcessing((byte) 0x72, scriptBuf, scriptBuf.length);
                LogUtil.e(TAG,"ret == " + ret  + "== scriptBuf==" + ByteTool.byte2hex(scriptBuf));
                if (ret == 0) return "9000";
            }else {
                 outStr = apduRead(ByteTool.hexStr2Bytes(command), ByteTool.hexStr2Bytes(dataInStr), 0xff);
                LogUtil.e(TAG, "outstr == " + outStr);

            }
        }
        return outStr;

    }

    public int ARPCExecuteScript2(int iCType, int authAmt, int cashbackAmt){

        String tc = "";
        try {
            int ret = -1;
            if(iCType >= 0 ){
//                ARPC = "01020304050607080303";
//                ScriptStr = "7251860F04DA9F790A000000000000A4B17D6D860F04DA9F770A0000001000008C09E6BF862D04DC010C2870229F61123433313232313139383830373136313231589F6201105F2006C5CBB0D8D3EEA168BB5A";
                //示例 5F2A02015672189F180400000001860F04DA9F790A00000009990048BC544882027C00910A989FB7628FD5BAC13030950500000008009A031201019C01609F02060000000000049F03060000000000049F101307010103A0A010040A010000100000AFA58FA69F1A0201569F2608EA8D99024C88726D9F2701809F330320A1009F34033F00009F360200159F370400000000
                LogUtil.e(TAG,"inARPC == " + ARPC);
                //解析出ARPC和脚本
                int index91 = ARPC.indexOf("910A");
                String inArpcStr = ARPC.substring(index91,index91 + 20 + 4);
                LogUtil.e(TAG,"inArpcStr == " + inArpcStr);
//                if (mCardCheckedType == ConstDefine.IC_CARD)
                    ret = externalAuth(inArpcStr);

                int index72 = ARPC.indexOf("71");
                // 没有71 有72 需要第二次GAC
                if (index72 < 0 || index72 > 12){
                    index72 = ARPC.indexOf("72");

                }
                if (mCardCheckedType == ConstDefine.IC_CARD){
                    //第二次GAC
                    byte[] rspCode = new byte[]{0x30, 0x30};
                    byte[] authCode = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
                    ret = mEmvCore.EmvLib2stGenAC(0x80, ErrorDefine.ONLINE_RET_APPROVE, rspCode, authCode, authCode.length);
                    LogUtil.e(TAG,"EmvLib2stGenAC iRet =" + ret);
                }else {

                    //第二次GAC
                    if (index72 > 0){
                        String tag8D = localTag8D;
                        LogUtil.e(TAG,"8D == " + tag8D);
//                        tag8D = "8D1D8A029F02069F03069F1A0295055F2A029A039C019F37049F21039F4E14";
                        LogUtil.e(TAG,"tag8D == " + tag8D); //示例 8D1D8A029F02069F03069F1A0295055F2A029A039C019F37049F21039F4E14
                        if (tag8D.length() > 4){
                            String cdol2 = processPDOL(tag8D);
                            LogUtil.e(TAG,"cdol2 == " + cdol2);
                            //80AE40002E00000000000900000000000001560000800000015610041000B84FBA072019024C4E00000000000000000000000000000000000000
                            byte[] command = ByteTool.hexStr2Bytes("80AE4000"); //Generate AC（获取应用密文）80 AE xx（控制参数 40 TC 和80 ARQC） 00
                            byte[] dataIn = ByteTool.hexStr2Bytes(cdol2);
                            String cdolOut = apduRead(command,dataIn,0xff);
                            LogUtil.e(TAG,"GAC2  cdol2Out == " + cdolOut + "----" + new String(ByteTool.hexStr2Bytes(cdolOut)) );
                            if (cdolOut.length() > 20  ) {
                                int totalLen = Integer.parseInt(cdolOut.substring(2, 4), 16);
                                LogUtil.e(TAG, "totalLen == " + totalLen);
                                String tag9F27 = cdolOut.substring(4, 6);  //应用密文信息 1
                                String tag9F36 = cdolOut.substring(6, 10); //计数器 2
                                String tag9F26 = cdolOut.substring(10, 26); // 应用密文 8
                                String tag9F10 = cdolOut.substring(26, totalLen * 2 - 22 + 26); //发卡行应用数据
                                tc = tag9F26;
                            }
                        }
                    }
                }


                int scriptLen = Integer.parseInt(ARPC.substring(index72+2,index72 + 4),16);

                ScriptStr = ARPC.substring(index72 ,index72 + scriptLen * 2 + 4);
                LogUtil.e(TAG,"ScriptStr == " + ScriptStr + "---- scriptLen == " + scriptLen);
                String ScriptResult = "";
                if (ARPC.length() > 20 || !TextUtils.isEmpty(ScriptStr)){
                    //执行脚本
                    String outStr = executeScript(ScriptStr);

                    if (mCardCheckedType == ConstDefine.IC_CARD){
                        //获取脚本执行结果
                        byte[] data1 = new byte[100];
                        int[] len = new int[1];
                        ret = mEmvCore.EmvLibGetScriptResult(data1,len);
                        ScriptResult = ByteTool.byte2hex(data1,0,len[0],false);
                        LogUtil.e(TAG,"EmvLibGetScriptResult ret ==" + ret + "-----" + ScriptResult);
                    }else {
                        if (outStr.equals("9000")){
                            ScriptResult = "200000000001";
                        }else {
                            ScriptResult = "110000000001";
                        }
                    }

                }

                int[] len = new int[1];
                byte[] dataOut = new byte[500];
                String wantTags[] = {"95","9F79","9F26"};
                ret = getTLV(wantTags,dataOut,len);
                String outStr = ByteTool.byte2hex(dataOut,0,len[0],false);
                LogUtil.e(TAG,"iRet == " + ret + " ------- " + outStr);

                if (mCardCheckedType == ConstDefine.IC_CARD)
                    tc = StringUtil.tagParse("9F26",outStr);

                Bundle bundle = new Bundle();
                bundle.putInt("result", ret);

                bundle.putString("ScriptResult",ScriptResult );


                bundle.putString("TC", tc);

                if(ret == 0){
                    deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                }else {
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                }


            }

        }catch (Exception e){
            e.printStackTrace();
            LogUtil.e(TAG,e.getMessage());

        }finally {
            if(iCType == 0){
                MainActivity.getmMainIcc().DLL_IccClose((byte) 0);
            }else {
                MainActivity.getmMainPicc().DLL_PiccClose();  //执行脚本后关闭
            }
        }

        return 0;
    }

    //接触式
    private int tranProcess(int authAmt, int cashbackAmt) {
        int iRet = -1;

        MainActivity.miTransCount++;

        AppList[] appList = new AppList[16];
        int[] listSize = new int[1];

        for (int i = 0; i < 16; i++) {
            appList[i] = new AppList();
        }

        System.out.println("tranProcess---EmvLibBuildCandidateList");
        iRet = mEmvCore.EmvLibBuildCandidateList(0, appList, listSize);
        LogUtil.e(TAG,"EmvLibBuildCandidateList iRet =" + iRet + " ---- listSize == " +  listSize[0]);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibSelectApp(0);
        LogUtil.e(TAG,"EmvLibSelectApp 0 iRet =" + iRet);
        if (0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibInitAppProcessing(0, MainActivity.miTransCount, authAmt, cashbackAmt);
        LogUtil.e(TAG,"EmvLibInitAppProcessing iRet =" + iRet);
        if (0 != iRet &&
                ErrorDefine.RET_ERR_APPSEL != iRet)
            return iRet;

        while (ErrorDefine.RET_ERR_APPSEL == iRet) {
            iRet = mEmvCore.EmvLibGetNewCandidateList(appList, listSize);
            LogUtil.e(TAG,"EmvLibGetNewCandidateList iRet =" + iRet);
            if (0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibSelectApp(0);
            LogUtil.e(TAG,"EmvLibSelectApp iRet =" + iRet);
            if (0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibInitAppProcessing(0, 1, authAmt, cashbackAmt);
            LogUtil.e(TAG,"EmvLibInitAppProcessing iRet =" + iRet);
            if (0 != iRet &&
                    ErrorDefine.RET_ERR_APPSEL != iRet)
                return iRet;
        }

        iRet = mEmvCore.EmvLibReadAppData();
        LogUtil.e(TAG,"EmvLibReadAppData iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibCheckExceptionPan();
        LogUtil.e(TAG,"EmvLibCheckExceptionPan iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibTerminalRiskManage();
        LogUtil.e(TAG,"EmvLibTerminalRiskManage iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibOfflineAuth();
        LogUtil.e(TAG,"EmvLibOfflineAuth iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibProcessingRestrictions();
        LogUtil.e(TAG,"EmvLibProcessingRestrictions iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibCardholderVerification();
        LogUtil.e(TAG,"EmvLibCardholderVerification iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        int acType = 0;
        acType = mEmvCore.EmvLibTerminalActionAnalysis();
        LogUtil.e(TAG,"EmvLibTerminalActionAnalysis acType =" + acType);
        if (ErrorDefine.ACTYPE_AAC == acType) {
            iRet = mEmvCore.EmvLib1stGenAC(acType);
            LogUtil.e(TAG,"EmvLib1stGenAC iRet =" + iRet);
            return iRet;
        } else {
            iRet = mEmvCore.EmvLib1stGenAC(acType);
//            iRet = EmvLib1stGenAC(acType);
            LogUtil.e(TAG,"EmvLib1stGenAC iRet ====" + iRet);
            if (iRet <= 0)
                return iRet;

            acType = iRet;

            //online process

            //online flow
//            byte[] authData = new byte[]{0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x2A, 0x2B};
//            if (authData.length > 0) {
//                mEmvCore.EmvLibHostAuth(authData, authData.length);
//                LogUtil.e(TAG,"EmvLibHostAuth iRet =" + iRet);
//            }


//            byte[] scriptBuf = new byte[]{0x71, 0x12, (byte) 0x9F, 0x18, 0x04, 0x11, 0x22, 0x33, 0x44, (byte) 0x86, 0x09, (byte) 0x84, 0x24, 0x00, 0x00, 0x04, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD};
//            if (scriptBuf.length > 0) {
//                int ret1 = mEmvCore.EmvLibScriptProcessing((byte) 0x71, scriptBuf, scriptBuf.length);
//                LogUtil.e(TAG,"EmvLibScriptProcessing iRet =" + ret1);
//                //获取脚本执行结果
//                byte[] data1 = new byte[100];
//                int[] len = new int[1];
//                int ret = mEmvCore.EmvLibGetScriptResult(data1,len);
//                LogUtil.e(TAG,"EmvLibGetScriptResult ret ==" + ret + "-----" + ByteTool.byte2hex(data1,0,len[0],false));
//                byte dataOut[] = new byte[100];
//
//                ret = getTLV(new String[]{"95","9F26"},dataOut,len);
//                LogUtil.e(TAG,"getTLV ret ==" + ret + "-----" + ByteTool.byte2hex(dataOut,0,len[0],false));
//
//            }

//            byte[] rspCode = new byte[]{0x30, 0x30};
//            byte[] authCode = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
//            iRet = mEmvCore.EmvLib2stGenAC(acType, ErrorDefine.ONLINE_RET_APPROVE, rspCode, authCode, authCode.length);
//            LogUtil.e(TAG,"EmvLib2stGenAC iRet =" + iRet);
//            scriptBuf = new byte[]{0x72, 0x12, (byte) 0x9F, 0x18, 0x04, 0x11, 0x22, 0x33, 0x44, (byte) 0x86, 0x09, (byte) 0x84, 0x24, 0x00, 0x00, 0x04, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD};
//            if (scriptBuf.length > 0) {
//                mEmvCore.EmvLibScriptProcessing((byte) 0x72, scriptBuf, scriptBuf.length);
//            }

            	return 0;
//            return iRet;
        }
    }
    //接触式获取数据
    private String tranProcess(int authAmt, int cashbackAmt,String inStr){
        int iRet = -1;
        byte[] command;
        byte[] dataIn;
        String outStr ;

        //读电子现金单笔交易限额
        command = ByteTool.hexStr2Bytes("80CA9F78");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x09);
//        LogUtil.e(TAG,"余额 outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F78 = StringUtil.tagParse(0,"9F78",outStr);
        if (inStr.contains("9F7800"))
            inStr = inStr.replace("9F7800","9F78" + String.format("%02X",tag9F78.length()/2) + tag9F78);

        //读余额
        command = ByteTool.hexStr2Bytes("80CA9F79");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x09);
//        LogUtil.e(TAG,"余额 outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F79 = StringUtil.tagParse(0,"9F79",outStr);
        if (inStr.contains("9F7900"))
            inStr = inStr.replace("9F7900","9F79" + String.format("%02X",tag9F79.length()/2) + tag9F79);

        //读电子现金余额上限
        command = ByteTool.hexStr2Bytes("80CA9F77");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x09);
//        LogUtil.e(TAG,"余额 outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F77 = StringUtil.tagParse(0,"9F77",outStr);
        if (inStr.contains("9F7700"))
            inStr = inStr.replace("9F7700","9F77" + String.format("%02X",tag9F77.length()/2) + tag9F77);

        return inStr;
    }
    public static  String localTag9F26 = "";
    public static  String localTag8D = "";
    public static String localTag95 = "0480000000";
    public static Map<String,String> tlvMap = new HashMap<>();
    /**
     * 非接 pboc
     * @param authAmt
     * @param cashbackAmt
     * @return
     */
    private String clTranProcess2(int authAmt, int cashbackAmt,String inStr) {

        tlvMap.clear(); //清空所有数据避免缓存

        if (inStr.contains("8200")){ // 应用交互特征(AIP) 7D00 7C00
            inStr = inStr.replace("8200","82027C00");
        }
        if (inStr.contains("9500")){
            inStr = inStr.replace("9500","9505" + localTag95);
        }
        if (inStr.contains("9A00")){ // 交易日期
            inStr = inStr.replace("9A00","9A03" + localDate);
        }
        if (inStr.contains("9C00")){
            inStr = inStr.replace("9C00","9C0100");
        }
        tlvMap.put("82","7C00");
        tlvMap.put("95",localTag95);
        tlvMap.put("9A",localDate);
        tlvMap.put("9C","00");
        getRandom8();
        int iRet = -1;
        byte[] command;
        byte[] dataIn;
        String outStr ;

        String tag8C = "";
        //选择环境
        command = new byte[]{0x00, (byte) 0xA4, (byte) 0x04, 0x00};
        dataIn = "1PAY.SYS.DDF01".getBytes();
        dataIn = ByteTool.hexStr2Bytes("325041592E5359532E4444463031"); //325041592E5359532E4444463031
        outStr = apduRead(command,dataIn,0x100);
        LogUtil.e(TAG,"outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)));

//        command = new byte[]{0x00, (byte) 0xB2, (byte) 0x01, 0x0C};
//        dataIn = new byte[0];
//        outStr = apduRead(command,dataIn,0x100);
//        LogUtil.e(TAG,"outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)));
//
//        for (int i = 2; i < 5; i++) {
//            command = new byte[]{0x00, (byte) 0xB2, (byte) i, 0x0C};
//            dataIn = new byte[0];
//            String out = apduRead(command,dataIn,0x100);
//            if (out.equals("6A83")){
//                break;
//            }
//        }


        //截取第一个Aid
        String aidStr = StringUtil.tagParse(8,"4F",outStr);
        LogUtil.e(TAG,"aidStr == " + aidStr);
//
        command = ByteTool.hexStr2Bytes("00A40400");
        dataIn = ByteTool.hexStr2Bytes(aidStr);
        outStr = apduRead(command,dataIn,0x100);
        LogUtil.e(TAG,"PDOL outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );


        String pDol = StringUtil.tagParse(5,"9F38",outStr);
        LogUtil.e(TAG,"PDOL == " + pDol);
        pDol = processPDOL(pDol);
        LogUtil.e(TAG,"转换后的 PDOL == " + pDol);
        //GPO
        command = ByteTool.hexStr2Bytes("80A80000");
        String data = "83" + String.format("%02X",pDol.length()/2) + pDol ;
        LogUtil.e(TAG,"inData == " + data);
        dataIn = ByteTool.hexStr2Bytes(data);
        outStr = apduRead(command,dataIn,0x100);

        LogUtil.e(TAG," GPO outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        //处理GPO 80167C00 08010100 10010101 10030600 18010100 20010100 9000
        int len = outStr.length() / 8;
        LogUtil.e(TAG,"len == " + len);
        for (int i = 0; i < len; i++) {
            String AFL = outStr.substring(i*8,i*8+8); //应用文件定位器
            LogUtil.e(TAG,"sfi == " + AFL);
            if (i == 0) continue;
            String sfi1 = AFL.substring(0,2);  // 读文件号格式为：SFI左移3位，右边补100。 比如08 十六进制就是 0000 1000 bit8-bit4才是SFI，所以真实的是：0000 0001 ，读取文件的时候，右补0100（表明读取指定记录） ，得到0000 1100，就是0x0c。同理，02文件就是：0x14
            String sfi2 = AFL.substring(2,4);  //字节2：文件中要读的第1个记录的记录号（不能为0）
            String sfi3 = AFL.substring(4,6); // 文件中要读的最后一个记录的记录号（大于或等于字节2）
            String sfi4 = AFL.substring(6,8); //从字节2的记录好开始，用于静态数据记录的个数（从0开始，不大于（字节3）-（字节2）+1）

            int sfi1Int = Integer.parseInt(sfi1,16);
            int afl =  sfi1Int + 0x04;
            String p2 = String.format("%02X",afl);

            int times = Integer.parseInt(sfi3 ,16) - Integer.parseInt(sfi2,16);
//            LogUtil.e(TAG,"times == " + times);
            for (int j = 0; j < times + 1; j++) {
                int sf2Int = Integer.parseInt(sfi2,16);
                String sfi2Str = String.format("%02X",sf2Int + j);
                String cmd = "00B2" + sfi2Str + p2;
                command = ByteTool.hexStr2Bytes(cmd);
                dataIn = new byte[0];
                String inner = apduRead(command,dataIn,0x100);
                LogUtil.e(TAG,sfi2Str + p2+ " inner == " + inner + "----" + new String(ByteTool.hexStr2Bytes(inner)) );

                //解析标签
                tlvMap.putAll(ConstTags.parseTLVTags(inner));

                //二磁道数据
                if (inner.contains("57") && inner.indexOf("57") == 4){
                    String tag57 = StringUtil.tagParse(0,"57",inner);
                    LogUtil.e(TAG,"57 ===" + tag57);
                    if (inStr.contains("5700") )
                        inStr = inStr.replace("5700","57" + String.format("%02X",tag57.length()/2) + tag57);

                }
                //获取证件类型 和证件号码   持卡人姓名 5F20
                if (inner.contains("9F61") && inner.contains("9F62")){
                    String tag9F61 = StringUtil.tagParse(0,"9F61",inner);
                    LogUtil.e(TAG,"tag9F61 ==== " + tag9F61);

                    if (inStr.contains("9F6100")){
                        inStr = inStr.replace("9F6100","9F61" + String.format("%02X",tag9F61.length()/2) + tag9F61);
                    }

                    String tag9F62 = StringUtil.tagParse(0,"9F62",inner);
                    LogUtil.e(TAG,"tag9F62 ==== " + tag9F62);
                    if (inStr.contains("9F6200"))
                        inStr = inStr.replace("9F6200","9F62" + String.format("%02X",tag9F62.length()/2) + tag9F62);

                    String tag5F20 = StringUtil.tagParse(0,"5F20",inner);
                    if (inStr.contains("5F2000"))
                        inStr = inStr.replace("5F2000","5F20" + String.format("%02X",tag5F20.length()/2) + tag5F20);

                }
                //5F34  应用主帐户序列号
                if (inner.contains("5F3401")){
                    String tag5F34 = StringUtil.tagParse(0,"5F34",inner);
                    LogUtil.e(TAG,"5f34 ===" + tag5F34);
                    if (inStr.contains("5F3400") )
                        inStr = inStr.replace("5F3400","5F34" + String.format("%02X",tag5F34.length()/2) + tag5F34);
                }

                //失效日期
                if (inner.contains("5F2403")){
                    String tag5F24 = StringUtil.tagParse(0,"5F24",inner);
                    LogUtil.e(TAG,"5f24 ===" + tag5F24);
                    if (inStr.contains("5F2400") )
                        inStr = inStr.replace("5F2400","5F24" + String.format("%02X",tag5F24.length()/2) + tag5F24);
                }
                if (inner.contains("9F1F")){ //1磁道数据
                    String tag9F1F = StringUtil.tagParse(0,"9F1F",inner);
                    LogUtil.e(TAG,"9F1F ===" + tag9F1F);
                    if (inStr.contains("9F1F00") && !tag9F1F.isEmpty())
                        inStr = inStr.replace("9F1F00","9F1F" + String.format("%02X",tag9F1F.length()/2) + tag9F1F);
                }
                //5F30 服务码  8C CDOL1  8D CDOL2  9F08 应用版本号 9F42 应用货币代码
                if (
                        (inner.contains("8C") &&
                         inner.contains("8D") &&
                         inner.contains("9F08")) ||
                                (inner.contains("8C") &&
                                        inner.contains("8D") &&
                                        inner.contains("5F30"))

                ){
                    try{
                        tag8C = StringUtil.tagParse(4,"8C",inner);
                        LogUtil.e(TAG,"tag8C == " + tag8C);
                        if (tag8C.length() > 0){
                            String tag8D = StringUtil.tagParse(4 + tag8C.length(),"8D",inner);
                            localTag8D = tag8D;
                            LogUtil.e(TAG,"tag8D == " + tag8D);
                        }else {
                            localTag8D = "";
                        }
                    }catch (StringIndexOutOfBoundsException e){
                        e.printStackTrace();

                    }

                }

            }

        }


        //读余额
        command = ByteTool.hexStr2Bytes("80CA9F79");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x09);
//        LogUtil.e(TAG,"余额 outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F79 = StringUtil.tagParse(0,"9F79",outStr);
        tlvMap.put("9F79",tag9F79);
        if (inStr.contains("9F7900"))
            inStr = inStr.replace("9F7900","9F79" + String.format("%02X",tag9F79.length()/2) + tag9F79);

        //读电子现金余额上限
        command = ByteTool.hexStr2Bytes("80CA9F77");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x09);
//        LogUtil.e(TAG,"余额 outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F77 = StringUtil.tagParse(0,"9F77",outStr);
        tlvMap.put("9F77",tag9F77);
        if (inStr.contains("9F7700"))
            inStr = inStr.replace("9F7700","9F77" + String.format("%02X",tag9F77.length()/2) + tag9F77);
        //读电子现金单笔交易限额
        command = ByteTool.hexStr2Bytes("80CA9F78");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x09);
//        LogUtil.e(TAG,"余额 outStr == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F78 = StringUtil.tagParse(0,"9F78",outStr);
        tlvMap.put("9F78",tag9F78);
        if (inStr.contains("9F7800"))
            inStr = inStr.replace("9F7800","9F78" + String.format("%02X",tag9F78.length()/2) + tag9F78);
        //读ATC
        command = ByteTool.hexStr2Bytes("80CA9F13");
        dataIn = ByteTool.hexStr2Bytes("");
        outStr = apduRead(command,dataIn,0x100);
        LogUtil.e(TAG,"outStr 9F13 == " + outStr + "----" + new String(ByteTool.hexStr2Bytes(outStr)) );
        String tag9F13 = StringUtil.tagParse(0,"9F13",outStr);
        tlvMap.put("9F13",tag9F13);
        //========== GAC1 =========================================================================================================
        if (TextUtils.isEmpty(tag8C)){
            tag8C = tlvMap.get("8C");
            localTag8D = tlvMap.get("8D");
        }
        String cdol1 = processPDOL(tag8C);
        LogUtil.e(TAG,"cdol1 == " + cdol1);

        //第一次GAC
        command = ByteTool.hexStr2Bytes("80AE8000"); //Generate AC（获取应用密文）80 AE xx（控制参数 40 TC 和80 ARQC） 00
        dataIn = ByteTool.hexStr2Bytes(cdol1);
        String cdolOut = apduRead(command,dataIn,0x100);
        LogUtil.e(TAG,"GAC1 cdol  cdolOut == " + cdolOut + "----" + new String(ByteTool.hexStr2Bytes(cdolOut)) );
        //解析应用交易数据 801E 80 4899 A458F2CC8A896254 07010103A0A800010A01000000000056872D2B 9000
        if (cdolOut.length() > 20  ){
            int totalLen = Integer.parseInt(cdolOut.substring(2,4),16);
            LogUtil.e(TAG,"totalLen == " + totalLen);
            String tag9F27 = cdolOut.substring(4,6);  //应用密文信息 1
            String tag9F36 = cdolOut.substring(6,10); //计数器 2
            String tag9F26 = cdolOut.substring(10,26); // 应用密文 8
            String tag9F10 = cdolOut.substring(26,totalLen * 2 - 22 + 26); //发卡行应用数据
            LogUtil.e(TAG,"9F27 == " + tag9F27 + "----9F36 == " + tag9F36 + "---- 9F26==" + tag9F26 + "---- 9F10 == " + tag9F10);
            tlvMap.put("9F27",tag9F27);
            tlvMap.put("9F36",tag9F36);
            tlvMap.put("9F26",tag9F26);
            tlvMap.put("9F10",tag9F10);
            if (inStr.contains("9F27")){ //交易计数器
                int index = inStr.indexOf("9F2701");
                String tag9F27Org = StringUtil.tagParse(index,"9F27",inStr); //取出原有的数据
                if (inStr.contains("9F2701") && !tag9F27Org.isEmpty())
                    inStr = inStr.replace("9F2701" + tag9F27Org,"9F2701" + tag9F27);
                if (index < 0 && inStr.contains("9F2700")){
                    inStr = inStr.replace("9F2700","9F2701" + tag9F27);
                }
            }

            if (inStr.contains("9F36")){ //交易计数器
                int index = inStr.indexOf("9F3602");
                String tag9F36Org = StringUtil.tagParse(index,"9F36",inStr); //取出原有的数据
                if (inStr.contains("9F3602") && !tag9F36Org.isEmpty())
                    inStr = inStr.replace("9F3602" + tag9F36Org,"9F3602" + tag9F36);

                if (index < 0 && inStr.contains("9F3600")){
                    inStr = inStr.replace("9F3600","9F3602" + tag9F36);
                }
            }

            if (inStr.contains("9F26")){ //应用密文
                int index = inStr.indexOf("9F2608");
                String tag9F26Org = StringUtil.tagParse(index,"9F26",inStr); //取出原有的数据
                if (inStr.contains("9F2608") && !tag9F26Org.isEmpty())
                    inStr = inStr.replace("9F2608" + tag9F26Org,"9F2608" + tag9F26);

                if (index < 0 && inStr.contains("9F2600")){
                    inStr = inStr.replace("9F2600","9F2608" + tag9F26);
                }
            }

            if (inStr.contains("9F10")){ //发卡行应用数据
                int index = inStr.indexOf("9F10");
                String tag9F10Org = StringUtil.tagParse(index,"9F10",inStr); //取出原有的数据
                if (inStr.contains("9F10") && !tag9F10Org.isEmpty()){
                    String lens = String.format("%02X",tag9F10Org.length()/2);
                    inStr = inStr.replace("9F10" + lens + tag9F10Org,"9F10"+ lens + tag9F10);
                }

                if ( inStr.contains("9F1000")){
                    inStr = inStr.replace("9F1000","9F10" + String.format("%02X",tag9F10.length()/2) + tag9F10);
                }
            }
        }


        if (inStr.contains("5F3400")){
            inStr = inStr.replace("5F3400","5F340101");
            tlvMap.put("5F34","01");
        }

        if (inStr.contains("9F0200")){ //授权金额
            inStr = inStr.replace("9F0200","9F0206000000000000");
            tlvMap.put("9F02","000000000000");
        }
        if (inStr.contains("9F0300")){ //其他金额
            inStr = inStr.replace("9F0300","9F0306000000000000");
            tlvMap.put("9F03","000000000000");
        }
        if (inStr.contains("5F2A00")){ // 交易货币代码 货币代码
            inStr = inStr.replace("5F2A00","5F2A020156");
        }
        tlvMap.put("5F2A","0156");
        if (inStr.contains("9F1A00")){ // 终端国家代码
            inStr = inStr.replace("9F1A00","9F1A020156");
        }
        tlvMap.put("9F1A","0156");

        if (inStr.contains("9F3300")){ // 终端终端性能 9F3303E0F0C8
            inStr = inStr.replace("9F3300","9F3303E0F0C8");
        }
        tlvMap.put("9F33","E0F0C8");

        if (inStr.contains("9F3700")){ // 随机数
            inStr = inStr.replace("9F3700","9F3704" + localRandom);
            tlvMap.put("9F37",localRandom);
        }
        for(String key : tlvMap.keySet()){
            LogUtil.e(TAG,"key == " + key +  " ---- value == " + tlvMap.get(key));
        }
        return inStr;
    }
    public String getRandom8(){
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString();
        // 去掉"-"符号
        StringBuffer temp = new StringBuffer();
        temp.append(str.substring(0, 8))
//                .append(str.substring(9, 13))
//                .append(str.substring(14, 18))
//                .append(str.substring(19, 23))
//                .append(str.substring(24))
        ;
        localRandom = temp.toString().toUpperCase();
        LogUtil.e(TAG,"localRand == " + localRandom);
        return localRandom;
    }
    private String localDate = getLocalDate();
    private String localRandom = "01020304";
    //CDOL2 8A02 9F0206 9F0306 9F1A02 9505 5F2A02 9A03 9C01 9F3704 9F2103 9F4E14
    //CDOL1 ：9F0206 9F0306 9F1A02 9505 5F2A02 9A03 9C01 9F3704 9F2103 9F4E14
    //        9F7A01 9F0206                    5F2A02                  DF6901
    //9F6604 9F0206 9F0306 9F1A02 9505 5F2A02 9A03 9C01 9F3704 9F2103 DF6901
    //9F6604  DF6001 9F0206 9F0306 9F1A02 9505 5F2A02 9A03 9C01 9F3704 DF6901
    //9F6604 9F0206 9F0306 9F1A02 9505 5F2A02 9A03 9C01 9F3704 DF6901  AE卡
    //36800080 00 000000000000 000000000000 0156 0000000000 0156 221021 00 4FE75F8A 01
    //36800080 01 000000000000 000000000000 0156 0000000000 0156 221021 00 00000000 01

    //9F6604 9F0206 9F0306 9F1A02 9505 5F2A02 9A03 9C01 9F3704 DF6001 DF6901 //贵州农信

    public String processPDOL(String pDol){
        if (TextUtils.isEmpty(pDol)) return "";
        StringBuffer sb = new StringBuffer();
        while (pDol.length() > 3 ) {
            String tag = pDol.substring(0,2);

            if (tag.equals("8A") ||tag.equals("95") || tag.equals("9A") || tag.equals("9C")){
                String sub = pDol.substring(0,4);
                if (sub.contains("8A02")) //授权响应码
                    sb.append("3030");

                if (sub.contains("9505")){
                    sb.append(localTag95);
                }
                if (sub.contains("9A03")){  //日期
                    localDate = getLocalDate();
                    sb.append(getLocalDate());
                }
                if (sub.contains("9C01")){
                    sb.append("00");
                }
                pDol = pDol.substring(4);

            }else {
                String sub = pDol.substring(0,6);
//                LogUtil.e(TAG,"sub2 == " + sub);
                if (sub.contains("9F6604")){ //终端交易属性
//            sb.append("36800080");
//            sb.append("60000000");
                    sb.append("54800000");
                }
                if (sub.contains("9F7A01")){ //电子现金指示器
                    sb.append("01");
                }

                if (sub.contains("9F0206")){
                    sb.append("000000000000");
                }
                if (sub.contains("9F0306")){
                    sb.append("000000000000");
                }
                if (sub.contains("9F1A02")){
                    sb.append("0156");
                }

                if (sub.contains("5F2A02")){
                    sb.append("0156");
                }

                if (sub.contains("9F3704")){
                    sb.append(localRandom);
                }
                if (sub.contains("9F2103")){ //时间
                    sb.append(getLocalTime());
                }
                if (sub.contains("DF6001")){ //CAPP交易指示位	如果卡片支持CAPP扩展应用交易，则需在PDOL中指明此数据指出终端支持的CAPP交易类型  分段付费标记 00不支持
                    sb.append("00");
                }
                if (sub.contains("DF6901")){ //SM算法指示器
                    sb.append("01");
                }

                if (sub.contains("9F4E14")){ //商户名称
                    sb.append("0000000000000000000000000000000000000000"); //0000000000000000000000000000000000000000
                }
                pDol = pDol.substring(6);
            }
        }

        return sb.toString();
    }


    public String getLocalTime(){
        Calendar cal = Calendar.getInstance();

        cal.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        String year = String.valueOf(cal.get(Calendar.YEAR));
        year = year.substring(2);
        String month = String.valueOf(cal.get(Calendar.MONTH) + 1);
        if ( month.length() == 1)
            month = "0" + month;
        String day = String.valueOf(cal.get(Calendar.DATE));
        if (day.length() == 1) day = "0" + day;
        String hour;
        if (cal.get(Calendar.AM_PM) == 0)
            hour = String.valueOf(cal.get(Calendar.HOUR));
        else
            hour = String.valueOf(cal.get(Calendar.HOUR)+12);

        if (hour.length() == 1) hour = "0" + hour;

        String minute = String.valueOf(cal.get(Calendar.MINUTE));
        if (minute.length() == 1) minute = "0" + minute;
        String second = String.valueOf(cal.get(Calendar.SECOND));
        if (second.length() == 1) second = "0" + second;
        String time = hour + minute + second;
        LogUtil.e(TAG, "time ==" + time);
        return time;
    }
    public String getLocalDate(){
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        String year = String.valueOf(cal.get(Calendar.YEAR));
        year = year.substring(2);
        String month = String.valueOf(cal.get(Calendar.MONTH) + 1);
        if ( month.length() == 1)
            month = "0" + month;
        String day = String.valueOf(cal.get(Calendar.DATE));
        if (day.length() == 1) day = "0" + day;
        return year + month + day;

    }


    //非接
    @Deprecated
    private int clTranProcess(int authAmt, int cashbackAmt)
    {
        int iRet = -1;

        AppList[] appList = new AppList[16];
        int[] listSize = new int[1];

        for(int i = 0; i < 16; i++)
        {
            appList[i] = new AppList();
        }

        iRet = mEmvCore.QpbocLibPreProcess(authAmt, cashbackAmt);
        System.out.println("clTranProcess---pbocLibPreProcess iRet: " + iRet);
        if(0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibBuildCandidateList(1, appList, listSize);
        if(0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibSelectApp(0);
        if(0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibInitAppProcessing(1, 0, authAmt, cashbackAmt);
        if(0 != iRet &&
                ErrorDefine.RET_ERR_APPSEL != iRet)
            return iRet;

        while(ErrorDefine.RET_ERR_APPSEL == iRet)
        {
            iRet = mEmvCore.EmvLibGetNewCandidateList(appList, listSize);
            if(0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibSelectApp(0);
            if(0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibInitAppProcessing(0, 1, authAmt, cashbackAmt);
            if(0 != iRet &&
                    ErrorDefine.RET_ERR_APPSEL != iRet)
                return iRet;
        }

        iRet = mEmvCore.EmvLibReadAppData();
//        LogUtil.e(TAG,"LibReadAppData ret == " + iRet);
        if(0 != iRet)
            return iRet;

        //-----新加风险校验和终端风险管理--------------------------------------------
//        iRet = mEmvCore.EmvLibCheckExceptionPan();
////        LogUtil.e(TAG,"EmvLibCheckExceptionPan iRet =" + iRet);
//        if (0 != iRet)
//            return iRet;
//
//        iRet = mEmvCore.EmvLibTerminalRiskManage();
////        LogUtil.e(TAG,"EmvLibTerminalRiskManage iRet =" + iRet);
//        if (0 != iRet)
//            return iRet;
        //----------------------------------------------------------------------------
        iRet = mEmvCore.EmvLibOfflineAuth();
        LogUtil.e(TAG,"LibOfflineAuth ret == " + iRet);
        if(0 != iRet)
            return iRet;


//        //-----处理限制----- 持卡人验证------------------------------------------------------------------
//        iRet = mEmvCore.EmvLibProcessingRestrictions();
////        LogUtil.e(TAG,"EmvLibProcessingRestrictions iRet =" + iRet);
//        if (0 != iRet)
//            return iRet;
//
//        iRet = mEmvCore.EmvLibCardholderVerification();
////        LogUtil.e(TAG,"EmvLibCardholderVerification iRet =" + iRet);
//        if (0 != iRet)
//            return iRet;
//        //-----------------------------------------------------------------------------------------
//        iRet = mEmvCore.QpbocLibTerminalActionAnalysis();
//        LogUtil.e(TAG,"pbocLibTerminalActionAnalysis ret == " + iRet);
//        if(ErrorDefine.ACTYPE_ARQC != iRet)
//            return iRet;

//
//        //online process
//        //
//        byte[] rspCode = new byte[]{0x30, 0x30};
//        byte[] authCode = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
//        iRet = mEmvCore.QpbocLibCompleteOnlineTrans(ErrorDefine.ONLINE_RET_APPROVE, rspCode, authCode, authCode.length);
//        LogUtil.e(TAG,"pbocLibCompleteOnlineTrans ret == " + iRet);
//        return iRet;
        return 0;
    }

    /**
     * 自动识别卡读取交易明细记录
     */
    public void autoReadCardLog() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        if(res==1){
//            financialModule.PowerOff();
//            SystemClock.sleep(1000);
//            financialModule.PowerOn();
//            SystemClock.sleep(3000);
//            financialModule.EmvLib_Init();
            res = openModule();
        }
        Log.e(TAG, "openModule:" + res);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                    break;
                }
            }
            SystemClock.sleep(100);
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {

                byte[] atr = new byte[20];
                res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                if (res != 0) {
                    continue;
                }
                if (getA108PLog((byte) 0x00) == 0) {

                    break;
                }
            }


            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLog((byte) 0x02) == 0) {

                    MainActivity.getmMainPicc().DLL_PiccClose();  //自动读交易明细后关闭
                    break;
                }
            }

            SystemClock.sleep(100);

        }
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 自动识别卡读取圈存记录
     */
    public void autoReadCardLoad() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        if(res==1){

            res = openModule();
        }
        Log.e(TAG, "openModule:" + res);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                    break;
                }
            }
            SystemClock.sleep(100);
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {

                byte[] atr = new byte[20];
                res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                if (res != 0) {
                    continue;
                }
                if (getA108PLoadLog((byte) 0x00) == 0) {

                    break;
                }
            }


            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLoadLog((byte) 0x01) == 0) {

                    MainActivity.getmMainPicc().DLL_PiccClose();  // 自动读交易日志后关闭
                    LogUtil.e(TAG,"autoReadCardLoad DLL_PiccClose-----" );
                    break;
                }
            }

            SystemClock.sleep(100);

        }
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 读社保卡
     */
    public void readSocialCard(){
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
        byte[] atr = new byte[20];
        byte[] cardTypeByt = new byte[2];
        byte[] serialNo = new byte[100];
        LogUtil.e(TAG,"runFlag ====" + runFlag);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    LogUtil.e(TAG, "readSocialCard timeOut!!");
                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));

                    return;
                }
            }
            SystemClock.sleep(100);
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {
                mCardCheckedType = ConstDefine.IC_CARD;
                LogUtil.e(TAG,"DLL_IccCheck 读IC卡 检查卡成功");

                res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                LogUtil.e(TAG,"ICC open res=" + res);

                if (res != 0) {
                    continue;
                }
                break;
            }

            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardTypeByt, serialNo) == 0) {
                mCardCheckedType = ConstDefine.PIC_CARD;
                LogUtil.e(TAG,"DLL_PiccCheck  检查卡成功");
                break;
            }
            SystemClock.sleep(100);
        }
        //检测到卡后继续读卡 -----------------------------------------------------
        try{
            readSocialBasicInfo();
        }catch (Exception e){
            e.printStackTrace();
        }


    }

    /**
     * 读社保卡基本信息
     */
    public void readSocialBasicInfo(){
        selectFileRoot();
        selectEnvironmentSSSE();
        String random1 = readRandom();
        random1 = random1.substring(0,random1.length() - 4);
        if (TextUtils.isEmpty(random1)){
            deliverError(ErrorDefine.CARD_TYPE_ERR,"read social card error");
            return;
        }
        LogUtil.e(TAG,"random1 == " + random1);
        String random2 = "1234567890ABCDEF";
        String interAuthData = internalAuthenticate(random1 + random2);
        LogUtil.e(TAG,"interAuthData == " + interAuthData);

        String random3 = "1122334455667788";
        String random4 = "99AABBCCDDEEFF00";

        selectFileEF((byte) 0x05);

        byte[] command = new byte[]{0x00, (byte) 0xB2, (byte) 0x01,0x05}; //EF05所有数据
        byte[] dataIn = new byte[0];
        String outStr = apduRead(command,dataIn,0x40);
        LogUtil.e(TAG,"outData == " + outStr);
        Bundle bundle = new Bundle();
        if (outStr.length() < 5){
            bundle.putInt(ConstDefine.CODE,ErrorDefine.LENGTH_ERR);
            bundle.putString(ConstDefine.MESSAGE,"read card length error");
            deliverResult(callback, DeviceInterface.Result.ERROR,bundle,isOnMain);
            return;
        }
        outStr = parseEF05Data(ByteTool.hexStr2Bytes(outStr.substring(0,outStr.length()-4)));

        if (cardVersion.startsWith("3")){
            bundle.putString("data",outStr);
            deliverResult(callback, DeviceInterface.Result.SUCCEED,bundle,isOnMain);

            deliverResult(callback, DeviceInterface.Result.COMPLETED,null,isOnMain);
            return;
        }
        //-EF06信息-----------------------------------------------
        //选择EF06 读取所有信息
        selectFileEF((byte) 0x06);

        //读社会保障卡号08
        command = new byte[]{0x00, (byte) 0xB2, (byte) 0x08,0x00};
        dataIn = new byte[0];
        String cardNo = apduRead(command,dataIn,0xff);
        cardNo = cardNo.substring(4,cardNo.length() - 4);
        cardNo = new String(ByteTool.hexStr2Bytes(cardNo));
        LogUtil.e(TAG,"cardNo == " + cardNo);
        outStr += "|" + cardNo;

        command = new byte[]{0x00, (byte) 0xB2, (byte) 0x01,0x05}; //读EF06 所有数据
        dataIn = new byte[0];

        bundle.putString("data",outStr);
        deliverResult(callback, DeviceInterface.Result.SUCCEED,bundle,isOnMain);
        deliverResult(callback, DeviceInterface.Result.COMPLETED,null,isOnMain);
    }

    String ef05Info = "",cardVersion = "";
    StringBuffer sb = new StringBuffer();
    public String parseEF05Data(byte[] ef05InfoByte){
        sb.setLength(0);
        ef05Info = "";
        int len = 0;
//        Log.e(TAG,"readShebaoEF05 全部数据 outdata == " + ByteTool.byte2hex(ef05InfoByte));
//        Log.e(TAG,"readShebaoEF05 String == " + new String(ef05InfoByte));
        //卡识别码 01    发卡地区行政区划代码（卡识别码前6位）
        len = ef05InfoByte[1];
        byte cardbt[] = new byte[len];
        System.arraycopy(ef05InfoByte,2,cardbt,0,len);
        String cardStr = ByteTool.byte2hex(cardbt);
        String cardIdentifyCode = cardStr;
        Log.e(TAG,"卡识别码01 String == " + cardStr);
        sb.append("|").append(cardStr);
        sb.append("|").append(cardStr.substring(0,6));
        //卡的类别 02
        len = 1;
        cardbt = new byte[len];
        System.arraycopy(ef05InfoByte,20,cardbt,0,len);
        cardStr = new String(cardbt);
        Log.e(TAG,"卡的类别02 String == " + cardStr);
//        sb.append("|").append(cardStr);

        //规范版本03
        len = 4;
        cardbt = new byte[len];
        System.arraycopy(ef05InfoByte,23,cardbt,0,len);
        cardStr = new String(cardbt);
        Log.e(TAG,"规范版本03 String == " + cardStr);
        sb.append("|").append(cardStr);
         cardVersion = cardStr;

        //初始化机构编码04
        len = 0x0c;
        cardbt = new byte[len];
        System.arraycopy(ef05InfoByte,29,cardbt,0,len);
        cardStr = ByteTool.byte2hex(cardbt);
        Log.e(TAG,"初始化机构编码04 String == " + cardStr);
//        sb.append("|").append(cardStr);

        //发卡日期05
        len = 0x04;
        cardbt = new byte[len];
        System.arraycopy(ef05InfoByte,43,cardbt,0,len);
        cardStr = ByteTool.byte2hex(cardbt);
        Log.e(TAG,"发卡日期05 String == " + cardStr);
        sb.append("|").append(cardStr);


        //卡有效期06
        len = 0x04;
        cardbt = new byte[len];
        System.arraycopy(ef05InfoByte,49,cardbt,0,len);
        cardStr = ByteTool.byte2hex(cardbt);
        Log.e(TAG,"卡有效期06 String == " + cardStr);
        sb.append("|").append(cardStr);


        //卡号07
        len = 0x09;
        cardbt = new byte[len];
        System.arraycopy(ef05InfoByte,55,cardbt,0,len);
        cardStr = new String(cardbt);
        Log.e(TAG,"卡号07 String == " + cardStr);
        sb.append("|").append(cardStr);
        ef05Info = sb.toString();
        LogUtil.e(TAG,"ef05Info == " + ef05Info);
        return ef05Info;
//        发卡地区行政区划代码（卡识别码前6位）、卡复位信息（仅取历史字节）、算法标识、卡识别码、内部认证过程因子、
//        内部认证鉴别所需的原始信息、外部认证过程因子、外部认证鉴别所需的原始信息，
    }
    
    //内部认证 返回内部认证数据
    public String internalAuthenticate(String random) {
        byte[] command = new byte[]{0x00, (byte) 0x88, (byte) 0x00, 0x00};
        byte[] dataIn = ByteTool.hexStr2Bytes(random);
        return apduRead(command,dataIn,0x08);
    }
    public void selectFileRoot() {
        byte[] command = new byte[]{0x00, (byte) 0xA4, (byte) 0x00, 0x00};
        byte[] dataIn = new byte[]{(byte) 0x3F, 0x00};
        apduRead(command,dataIn,0xff);
    }
    public void selectEnvironmentSSSE() {

        byte[] command = new byte[]{0x00, (byte) 0xA4, (byte) 0x04, 0x00};
        byte[] dataIn = ByteTool.hexStr2Bytes("7378312E73682EC9E7BBE1B1A3D5CF"); //7378312E73682EC9E7BBE1B1A3D5CF
        apduRead(command,dataIn,0xff);
    }

    /**
     * 选择文件 EF05 EF06 等
     * @param num 05 或 06
     */
    public String selectFileEF(byte num) {
        //byte[] Command, short Lc, byte[] DataIn, short Le
        byte[] command = new byte[]{0x00, (byte) 0xA4, (byte) 0x02, 0x00};
        byte[] dataIn = new byte[]{(byte) 0xEF, (byte) (num & 0xff)};
        return apduRead(command,dataIn,0xff);
    }
    public String readRandom(){

        byte[] command = new byte[]{0x00, (byte) 0x84, (byte) 0x00,0x00};
        byte[] dataIn = new byte[0];
        return apduRead(command,dataIn,8);

    }

    public String apduRead(byte[] command,byte[] daIn,int wantLen){
        int ret = -1;
        byte[] dataOut = new byte[1024];
        int len = command.length + 2 + daIn.length + 2;
        byte[] dataIn = new byte[len];
        System.arraycopy(command,0,dataIn,0,command.length);
        byte[] lenByte = ByteTool.int2Bytes(daIn.length);
        dataIn[4] = lenByte[0];
        dataIn[5] = lenByte[1];
        System.arraycopy(daIn,0,dataIn,6,daIn.length); //把需要的数据写入
        lenByte = ByteTool.int2Bytes(wantLen);
        dataIn[daIn.length + 6] = lenByte[0];
        dataIn[daIn.length + 7] = lenByte[1];
        LogUtil.e(TAG,"dataIn ================== " + ByteTool.byte2hex(dataIn));
        try{
            if (mCardCheckedType == ConstDefine.IC_CARD){
                ret = MainActivity.getmMainIcc().DLL_IccCommand((byte) 0,dataIn,dataOut);
            }
            if (mCardCheckedType == ConstDefine.PIC_CARD){
                ret = MainActivity.getmMainPicc().DLL_PiccCommand(dataIn,dataOut);
//                Thread.sleep(100);
//                LogUtil.e(TAG, " ---- dataOut == " + ByteTool.byte2hex(dataOut));
            }
            int dLen = (dataOut[0]&0xff) * 256 + (dataOut[1]&0xff) + 4;
            String outStr = ByteTool.byte2hex(dataOut,0,dLen,false);
            LogUtil.e(TAG,"ret == " + ret + " -- dlen == " + dLen  +  " ---- dataOut == " + outStr);
//            LogUtil.e(TAG, "dataOut ================== " + outStr);
            if (outStr.length() > 4){
                outStr = outStr.substring(4);
            }
            return outStr;
        }catch (Exception e){
            e.printStackTrace();
            ret = ErrorDefine.APDU_ERROR;
        }
        return "";
    }

    /**
     * IC卡 和 非接卡上电
     * @return
     */
    public int icCardPowerOn(){
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
        byte[] atr = new byte[20];
        byte[] cardTypeByt = new byte[2];
        byte[] serialNo = new byte[100];
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }
            SystemClock.sleep(100);
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {
                mCardCheckedType = ConstDefine.IC_CARD;
                LogUtil.e(TAG,"DLL_IccCheck 读IC卡 检查卡成功");

                res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                LogUtil.e(TAG,"ICC open res=" + res);


                if (res != 0) {
                    continue;
                }else {
                    Bundle bundle = new Bundle();
                    bundle.putString("data",ByteTool.byte2hex(atr));
                    deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                }
                deliverResult(callback, DeviceInterface.Result.COMPLETED, null, isOnMain);
                break;
            }

            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardTypeByt, serialNo) == 0) {
                mCardCheckedType = ConstDefine.PIC_CARD;
                res = 0;
                Bundle bundle = new Bundle();
                bundle.putString("data",ByteTool.byte2hex(serialNo));
                deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                deliverResult(callback, DeviceInterface.Result.COMPLETED, null, isOnMain);
                break;
            }

            SystemClock.sleep(100);

        }

        return res;
    }

    public void icCardApdu(){
        byte[] dataOut = new byte[1024];
        byte[] dataIn = ByteTool.hexStr2Bytes(ARPC);
//        byte[] apduSend = new byte[1024];
//        System.arraycopy(dataIn,0,apduSend,0,dataIn.length);
        int ret = -1;
        LogUtil.e(TAG,"mCardCheckedType == " + mCardCheckedType + " ----- cmd == " + ARPC);
        try{
            if (mCardCheckedType == ConstDefine.IC_CARD){
                ret = MainActivity.getmMainIcc().DLL_IccCommand((byte) 0,dataIn,dataOut);

            }
            if (mCardCheckedType == ConstDefine.PIC_CARD){
                ret = MainActivity.getmMainPicc().DLL_PiccCommand(dataIn,dataOut);
            }
            int dLen = (dataOut[0]&0xFF) * 256 + (dataOut[1]&0xff) + 4;
            LogUtil.e(TAG,"ret == " + ret + " ---- out == " + ByteTool.byte2hex(dataOut,0,dLen,false));
        }catch (Exception e){
            e.printStackTrace();
            ret = ErrorDefine.APDU_ERROR;
        }

        Bundle bundle = new Bundle();
        if (ret == 0){
            int len = (dataOut[0]&0xff) * 256 + dataOut[1]&0xff;
            byte[] data = new byte[len + 4];
            System.arraycopy(dataOut,0,data,0,len + 4);
            bundle.putString("data",ByteTool.byte2hex(data));
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
        }else {
            bundle.putInt("code",ret);
            bundle.putString("message",ErrorDefine.getErrorDescribe(ret));
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
        }
        deliverResult(callback, DeviceInterface.Result.COMPLETED, null, isOnMain);

    }

    /**
     * 自动识别卡类型
     */
    public void autoReadCardInfo() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
//        res = MainActivity.getmMainPicc().DLL_PiccOpen();
         res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
        LogUtil.e(TAG,"autoReadCardInfo picc open res" + res);

        res = MainActivity.getMainMcr().DLL_McrOpen();
        if(res==1){
//            financialModule.PowerOff();
//            SystemClock.sleep(1000);
//            financialModule.PowerOn();
//            SystemClock.sleep(3000);
//            financialModule.EmvLib_Init();
//            res = openModule();
            res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电;
            res = MainActivity.getMainMcr().DLL_McrOpen();
        }
        Log.e(TAG, "autoReadCardInfo openModule:" + res);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                        break;
                    }
                }
                SystemClock.sleep(100);
                if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {


                    LogUtil.e(TAG,"autoReadCardInfo 读IC卡 检查卡成功");
                    byte[] atr = new byte[20];
                    res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                    LogUtil.e(TAG,"ICC open res=" + res);

                    if (res == 1) {
//                        financialModule.PowerOff();
//                        SystemClock.sleep(1000);
//                        financialModule.PowerOn();
//                        SystemClock.sleep(3000);
//
//                        financialModule.EmvLib_Init();
                        continue;
                    }
                    if (res != 0) {
                        continue;
                    }
                    if (transBeforeOnline((byte) 0x00) == 0) {

                        break;
                    }
                }


                byte[] cardType = new byte[2];
                byte[] serialNo = new byte[100];
                if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardType, serialNo) == 0) {
                    if (transBeforeOnline((byte) 0x02) == 0) {
//                        MainActivity.getmMainPicc().DLL_PiccClose();

                        break;
                    }
                }

                SystemClock.sleep(100);
                if (BuildConfig.FLAVOR != ConstDefine.FLAVOR_GZNX){ //贵州农信 自动模式不刷卡
                    if (MainActivity.getMainMcr().DLL_McrCheck() == 0) {
                        if (mcrRead()) {
                            MainActivity.getMainMcr().DLL_McrClose();
                            break;
                        }
                    }
                    SystemClock.sleep(100);
                }


            }
        }finally {
//            IDCReadInterface.DLL_IDClose(); // 身份证NFC模块下电
//            closeModule();
            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }

    }

    /**
     * 自动检测 三种卡类型  检测到磁条卡时 返回读到的磁条数据
     */
    public void autoReadCheckCard() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
        LogUtil.e(TAG,"autoReadCardInfo picc open res" + res);

        res = MainActivity.getMainMcr().DLL_McrOpen();
        if(res==1){

            res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电;
            res = MainActivity.getMainMcr().DLL_McrOpen();
        }
        Log.e(TAG, "autoReadCardInfo openModule:" + res);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                        break;
                    }
                }
                SystemClock.sleep(100);
                if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {


                    LogUtil.e(TAG,"autoReadCardInfo 读IC卡 检查卡成功");
                    byte[] atr = new byte[20];
                    res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                    LogUtil.e(TAG,"ICC open res=" + res);

                    if (res != 0) {
                        continue;
                    }

                    Bundle bundle = new Bundle();
                    bundle.putParcelable("data", null);
                    bundle.putInt("slot",1);  // 0 磁条卡  1 插卡  2  非接卡
                    deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                    break;

                }

                byte[] cardType = new byte[2];
                byte[] serialNo = new byte[100];
                if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardType, serialNo) == 0) {
                    Bundle bundle = new Bundle();
                    bundle.putParcelable("data", null);
                    bundle.putInt("slot",2);  // 0 磁条卡  1 插卡  2  非接卡
                    deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                    break;
                }
                SystemClock.sleep(100);
                if (MainActivity.getMainMcr().DLL_McrCheck() == 0) {
                    if (mcrRead()) {
                        MainActivity.getMainMcr().DLL_McrClose();
                        break;
                    }
                }
                SystemClock.sleep(100);

            }
        }finally {

            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }

    }

    public void readPicLoadLog() {
        Timer tm = openPicc();
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.PIC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.PIC_CRAD_TIMEOUT));
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLoadLog((byte) 0x01) == 0) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        MainActivity.getmMainPicc().DLL_PiccClose(); //PIC 日志
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    public void readIcLoadLog() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {
                byte[] atr = new byte[20];
                int res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                if (res == 1) {
//                    financialModule.PowerOff();
//                    SystemClock.sleep(1000);
//                    financialModule.PowerOn();
//                    SystemClock.sleep(3000);
//
//                    financialModule.EmvLib_Init();
                    continue;
                }
                if (res != 0) {
                    continue;
                }
                if (getA108PLoadLog((byte) 0x00) == 0) {

                    break;
                }

            }
            SystemClock.sleep(200);
        }
        MainActivity.getmMainIcc().DLL_IccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);


    }

    public void readPicLog() {
        Timer tm = openPicc();
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.PIC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.PIC_CRAD_TIMEOUT));
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLog((byte) 0x01) == 0) {

                    break;
                }
            }
            SystemClock.sleep(100);
        }
        MainActivity.getmMainPicc().DLL_PiccClose(); //关闭非接卡
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 读IC交易明细
     */
    public void readIcLog() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {
                LogUtil.e(TAG,"已检测到 IC卡");
                byte[] atr = new byte[20];
                int res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                LogUtil.e(TAG," IC卡DLL_IccOpen=" + res);
                if (res != 0) {
                    continue;
                }
                if (getA108PLog((byte) 0x00) == 0) {
                    break;
                }

            }
            SystemClock.sleep(200);
        }
        MainActivity.getmMainIcc().DLL_IccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }
    @Deprecated
    public int getLoadLog(int cardType) {
        int ret = -1;
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");// 设置日期格式
        String time = df.format(new Date());
        ret = financialModule.setDateTime(ByteTool.hexStr2Bytes(time));
        if (ret != 0) {
            deliverError(ErrorDefine.SET_TIME_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_TIME_ERR));
            return -1;
        }
        ret = setEMVParam();
        if (ret != 0) {
            deliverError(ErrorDefine.SET_EMVPARAM_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_EMVPARAM_ERR));
            return -2;
        }
        byte[] tlog = new byte[1024];
        int[] num = new int[1];
        int res = -1;
        if (cardType == 0x00) {
            res = financialModule.EmvLib_GetLoadLog((byte) 0x00, tlog, num);
        } else if (cardType == 0x02) {
            res = financialModule.EmvLib_GetLoadLog((byte) 0x01, tlog, num);

        }
        Log.e("EmvLib_GetLog:", res + "--");
        if (res != 0) {
            deliverError(ErrorDefine.GET_LOE_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_LOE_ERR));
            return res;
        }
        List<LoadLogBean> list = parseLoadLog(tlog);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<LoadLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
        return res;
    }

    /**
     * 读圈存交易日志
     * @param cardType
     * @return
     */
    public int getA108PLoadLog(int cardType){
        int ret = -1;
        ret=  mEmvCore.EmvLibInitReadLog(cardType);
        LogUtil.e(TAG,"EmvLibInitReadLog ret ="  + ret);
        if(ret != 0){
            deliverError(ErrorDefine.EMV_INIT_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_INIT_ERR));
            return ret;
        }
//        //标签对应数据：交易日期3，交易时间3，授权金额6，其他金额6，终端国家代码2，交易货币代码2，商户名称20，交易类型1，应用交易计数器 2
//        int[] tags = new int[]{0x9A,0x9F21,0x9F02,0x9F03,0x9F1A,0x5F2A,0x9F4E,0x9C,0x9F36};
//        int[] dlen = new int[]{3,   3,     6,     6,     2,     2,     20,     1,   2    };
        //标签对应数据：授权金额6，其他金额6，交易货币代码2，交易类型1，终端国家代码2，应用交易计数器 2,交易日期3，交易时间3，商户名称20，
        int[] tags = new int[]{0x9F02,0x9F03,0x5F2A,0x9C,0x9F1A,0x9F36,0x9A,0x9F21,0x9F4E};
//        int[] dlen = new int[]{6,     6,      2,    1,    2,     2 ,    3,   3,     20    };
        byte[] allData = new byte[1024];
        for(int i=1;i<11;i++){
            ret = mEmvCore.EmvLibReadLoadLogRd(i);
            LogUtil.e(TAG,"--" + i +  "--请求读取一条圈存交易日志 ret ="  + ret);
            if (ret == 0){ //读取成功 之后再去取数据
                byte[] dataOut = new byte[20];
                int[] outLen = new int[1];
                int len = 0;
                for(int j=0; j<tags.length; j++){
                    ret = mEmvCore.EmvLibReadLoadLogItem(tags[j], dataOut,outLen);
                    LogUtil.e(TAG,"outLen--" + outLen[0] + "--"  + String.format("%02x", tags[j]) + "--Log读取成功：" + ByteTool.byte2hex(dataOut));
                    if (ret == 0){ //取数据成功
                        allData[0] = (byte) i;
                        int desPOs = 1 + len + (i-1)*45;
                        LogUtil.e(TAG,  "len ="  + len +  "------j==" + j + "-------desPOs==" + desPOs);
                        System.arraycopy(dataOut,0,allData,desPOs,outLen[0]);
                        len += outLen[0];
                        LogUtil.e(TAG,ByteTool.byte2hex(allData));
                    }
                }

            }else {
                if(i == 1 && ret == -17){//没有交易日志
                    LogUtil.e(TAG,"没有交易日志");
//                    deliverError(ErrorDefine.RET_ERR_NORECORD, ErrorDefine.getErrorDescribe(ErrorDefine.RET_ERR_NORECORD));
                }
                break;
            }

        }
        List<TradeLogBean> list = parseLog(allData);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;
    }

    public int getA108PLog(int cardType){
        int ret = -1;
        ret=  mEmvCore.EmvLibInitReadLog(cardType);
        LogUtil.e(TAG,"EmvLibInitReadLog ret ="  + ret);
        if(ret != 0){
            deliverError(ErrorDefine.EMV_INIT_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_INIT_ERR));
            return ret;
        }
//        //标签对应数据：交易日期3，交易时间3，授权金额6，其他金额6，终端国家代码2，交易货币代码2，商户名称20，交易类型1，应用交易计数器 2
//        int[] tags = new int[]{0x9A,0x9F21,0x9F02,0x9F03,0x9F1A,0x5F2A,0x9F4E,0x9C,0x9F36};
//        int[] dlen = new int[]{3,   3,     6,     6,     2,     2,     20,     1,   2    };
        //标签对应数据：授权金额6，其他金额6，交易货币代码2，交易类型1，终端国家代码2，应用交易计数器 2,交易日期3，交易时间3，商户名称20，
        int[] tags = new int[]{0x9F02,0x9F03,0x5F2A,0x9C,0x9F1A,0x9F36,0x9A,0x9F21,0x9F4E};
//        int[] dlen = new int[]{6,     6,      2,    1,    2,     2 ,    3,   3,     20    };
        byte[] allData = new byte[1024];
        for(int i=1;i<11;i++){
            ret = mEmvCore.EmvLibReadTxLogRd(i);
            LogUtil.e(TAG,"--" + i +  "--请求读取一条交易日志 ret ="  + ret);
            if (ret == 0){ //读取成功 之后再去取数据
                byte[] dataOut = new byte[20];
                int[] outLen = new int[1];
                int len = 0;
                for(int j=0; j<tags.length; j++){
                    ret = mEmvCore.EmvLibReadTxLogItem(tags[j], dataOut,outLen);
//                    LogUtil.e(TAG,"outLen--" + outLen[0] + "--"  + String.format("%02x", tags[j]) + "--Log读取成功：" + ByteTool.byte2hex(dataOut));
                    if (ret == 0){ //取数据成功
                        allData[0] = (byte) i;
                        int desPOs = 1 + len + (i-1)*45;
//                        LogUtil.e(TAG,  "len ="  + len +  "------j==" + j + "-------desPOs==" + desPOs);
                        System.arraycopy(dataOut,0,allData,desPOs,outLen[0]);
                        len += outLen[0];
//                        LogUtil.e(TAG,ByteTool.byte2hex(allData));
                    }
                }

            }else {
                break;
            }

        }
        List<TradeLogBean> list = parseLog(allData);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;
    }
    @Deprecated
    public int getLog(int cardType) {
        int ret = -1;
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");// 设置日期格式
        String time = df.format(new Date());
        ret = financialModule.EmvLib_SetParam(ByteTool.hexStr2Bytes(time));
        if (ret != 0) {
            deliverError(ErrorDefine.SET_TIME_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_TIME_ERR));
            return -1;
        }
        ret = setEMVParam();
        if (ret != 0) {
            deliverError(ErrorDefine.SET_EMVPARAM_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_EMVPARAM_ERR));
            return -2;
        }
        byte[] tlog = new byte[1024];
        int[] num = new int[1];
        int res = -1;
        if (cardType == 0x00) {
            res = financialModule.EmvLib_GetLog((byte) 0x00, tlog, num);
        } else if (cardType == 0x02) {
            res = financialModule.EmvLib_GetLog((byte) 0x01, tlog, num);

        }
        Log.e("EmvLib_GetLog:", res + "--");
        if (res != 0) {
            deliverError(ErrorDefine.GET_LOE_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_LOE_ERR));
            return res;
        }
        List<TradeLogBean> list = parseLog(tlog);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
        return res;
    }

    public void readPiccInfo() {
        Timer tm = openPicc();
        if (tm == null) {
            return;
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.PIC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.PIC_CRAD_TIMEOUT));
                        break;
                    }
                }
                byte[] cardType = new byte[2];
                byte[] serialNo = new byte[100];
                int ret = MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardType, serialNo);
                LogUtil.e(TAG,"开始检测非接。ret==" + ret);
                if (ret == 0) {
                    LogUtil.e(TAG,"检测非接卡成功。");
                    if (transBeforeOnline((byte) 0x02) == 0) {
                        break;
                    }
                } else if (ret == 1) {
                    LogUtil.e(TAG,"检测非接卡失败。res = 1");

                }

                SystemClock.sleep(300);
            }
        } finally {

//            MainActivity.getmMainPicc().DLL_PiccClose();
//            IDCReadInterface.gpio_control(46,0); //
//            IDCReadInterface.DLL_IDClose();
            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

        }


    }

    public void readIcCardInfo() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        LogUtil.e(TAG,"开始读卡");
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");

                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }

            int ret = MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00);
            LogUtil.e(TAG,"检卡 ret =" + ret);
            if ( ret == 0) {
                LogUtil.e(TAG,"readIcCardInfo 读IC卡 检查卡成功");
                byte[] atr = new byte[20];
                int res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                LogUtil.e(TAG,"ICC open res=" + res);
                if (res == 1) {

                    continue;
                }
                if (res != 0) {

                    continue;
                }
                if (transBeforeOnline((byte) 0x00) == 0) {

                    break;
                }

            } else  {
                LogUtil.e(TAG,"ICC检卡失败");
                continue;
            }
            SystemClock.sleep(500);
        }
//        MainActivity.getmMainIcc().DLL_IccClose((byte)0);  //不能关闭IC 后面还需要交易ARPC
        LogUtil.e(TAG,"DLL_IccClose");
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    /**
     *
     * @param cardType 卡类型 0--IC卡    2 非接卡
     * @return
     */
    public int transBeforeOnline(int cardType) {
        int iRet = -1;
        int TransNo = 1;
        int authorizedAmount = 0;
        int cashbackAmt = 0;

        mEmvCore = MainActivity.getEmvCore();
//      设置交易参数不起作用
//        TerminalData terminalData = new TerminalData();
//        mEmvCore.EmvLibGetTerminalData(terminalData);
//        LogUtil.e(TAG,"mTermType == " + terminalData.mTermType + " --- " + terminalData.mTransType +
//                " -- " + terminalData.mForceOnline + "---" + terminalData.mSupportPSESel);
//        terminalData.mTermType = 0x21;
//        terminalData.mTransType = 0x02;
//        terminalData.mForceOnline = 0x00;
//        terminalData.mSupportPSESel = 0x01;
//        iRet = mEmvCore.EmvLibSetTerminalData(terminalData);
//        LogUtil.e(TAG,"mEmvCore.EmvLibSetTerminalData == " + iRet );
        if (cardType == ConstDefine.IC_CARD
            || cardType == ConstDefine.PIC_CARD
        ){
            iRet = addApp();
            LogUtil.e(TAG,"addApp == " + iRet);
        }


        iRet = addCAPubKey();
        LogUtil.e(TAG,"addCAPubKey == " + iRet);

        if(iRet != 0){
            deliverError(ErrorDefine.EMV_CREATE_APP_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_CREATE_APP_ERR));
            return -1;
        }

//        iRet = addCAPubKey();
//        LogUtil.e(TAG,"addCAPubKey=" + iRet);
//        if(iRet != 0){
//            deliverError(ErrorDefine.EMV_CREATE_APP_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_CREATE_APP_ERR));
//            return -11;
//        }
        if(cardType == 0){  //接触式IC
            mCardCheckedType = ConstDefine.IC_CARD;
            iRet = tranProcess(authorizedAmount,cashbackAmt);

            LogUtil.e(TAG,"tranProcess ret == " + iRet);
            if(iRet != 0){
                return iRet;
            }
        }
        if(cardType == 2){ //非接IC
            mCardCheckedType = ConstDefine.PIC_CARD;
//            clTranProcess2(authorizedAmount,cashbackAmt,"");
//            iRet = clTranProcess(authorizedAmount,cashbackAmt);
//            LogUtil.e(TAG,"Process ret == " + iRet);
            iRet = 0;
            if(iRet != 0){
                return iRet;
            }

        }

        if (wantTags == null) {

            //银行所需标准55域
            wantTags = new String[]{"9F26", "9F27", "9F10", "9F37", "9F36", "95", "9A", "9C", "9F02", "5F2A", "82", "9F1A", "9F03", "9F33"};
            wantTags = new String[]{"5A", "57", "5F20", "9F62", "9F61",  "9F1F", "9F79", "9F77", "5F24", "5F34",
                    "9F26", "9F27", "9F10", "9F37", "9F36", "95", "9A", "9C", "9F02", "5F2A", "82", "9F1A", "9F03", "9F33",
//                    "9F34",
                    "9F78", "9F42"};
        }

        int[] len = new int[1];
        byte[] dataOut = new byte[500];

        iRet = getTLV(wantTags,dataOut,len);

        if (mCardCheckedType == ConstDefine.PIC_CARD){
            getTLVEmpty(wantTags,dataOut,len);
        }
        if (iRet != 0) {
            Log.v(TAG, "EmvLib_GetTags: ret = " + iRet);
            deliverError(ErrorDefine.GET_TAGS_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_TAGS_ERR));
            return -9;
        }
        byte[] out = new byte[len[0]];
        System.arraycopy(dataOut, 0, out, 0, len[0]);
        String returnstring = ByteTool.byte2hex(out);

        //处理交易数据
        if (cardType == ConstDefine.IC_CARD){
            mCardCheckedType = ConstDefine.IC_CARD;
            returnstring = tranProcess(authorizedAmount,cashbackAmt,returnstring);
        }
        else {
            mCardCheckedType = ConstDefine.PIC_CARD;
            returnstring = clTranProcess2(authorizedAmount,cashbackAmt,returnstring);

            //根据传入的标签来获取所有标签数据
            getTLVByMap(wantTags,tlvMap);
        }


        int len5A = StringUtil.getTagLen(0, "5A", returnstring);
        String tag57 = StringUtil.tagParse(len5A * 2 + 4, "57", returnstring);
        String cardNo = getCardNo(tag57);

        Log.e(TAG, "tag57 == " + tag57 + "---");
        int len57 = StringUtil.getTagLen(len5A * 2 + 4, "57", returnstring);
        if (returnstring.startsWith("5A00") && len57 > 12){

            if (cardNo!= null && cardNo.length()%2 != 0){
                cardNo = cardNo + "F";
            }

            String tag5A = "5A" + String.format("%02X",cardNo.length()/2) + cardNo;
            returnstring = returnstring.replace("5A00",tag5A);

        }


        BankCardInfoBean bean = new BankCardInfoBean();

        bean.setCardType(cardType);

        bean.twoMagneticTrack = tag57;

        bean.setCardNo(getCardNo(tag57));

//        returnstring = returnstring.substring(returnstring.indexOf("9F26"));
//        returnstring = returnstring.substring(0,returnstring.indexOf("9F34"));

        bean.setICChipData(returnstring);//.substring(len5A * 2 + 8 + len57 * 2)
        Bundle bundle = new Bundle();
        bundle.putParcelable("data", bean);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;
    }
    public String getTLVByMap(String[] tlvList,Map<String,String> map){
        StringBuffer sb = new StringBuffer();
        for (String tlv : tlvList){
            if (map.containsKey(tlv)){
                sb.append(tlv);
                String value = map.get(tlv);
                sb.append(String.format("%02X",value.length()/2));
                sb.append(value);
            }else {
                sb.append(tlv);
                sb.append("00");
            }
        }
        LogUtil.e(TAG,"all tag Str == " + sb.toString());
        return sb.toString();
    }
    public void getTLVEmpty(String[] tags, byte[] dataOut, int[] tLen){
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i< tags.length; i++){
            sb.append(tags[i]);
            sb.append("00");
        }
        byte[] tv = ByteTool.hexStr2Bytes(sb.toString());
        tLen[0] = tv.length;
        System.arraycopy(tv,0,dataOut,0,tv.length);
    }
    public int getTLV(String tags[],byte dataOut[],int tLen[]){
        int iRet = -1;
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i< tags.length; i++){

            byte byt[] = ByteTool.hexStr2Bytes(tags[i]);
            short tag = (short) (byt[0] & 0xFF);
            if(byt.length == 2){
                tag = (short) (((byt[0]&0xFF) << 8) + (byt[1]&0xFF));
            }

            byte dOut[]  = new byte[256];
            int len[] = new int[1];
            iRet = mEmvCore.EmvLibGetTLV(tag,dOut,len);
            if(iRet == 0){
                sb.append(tags[i]);
                sb.append(String.format("%02x", len[0]));
                sb.append(ByteTool.bytearrayToHexString(dOut,len[0]));
            }else {
                if(tags[i].equals("9F03")){
                    sb.append(tags[i]);
                    sb.append("06000000000000");
                }else {
                    sb.append(tags[i]);
                    sb.append("00");
                }
            }
        }
        byte[] tv = ByteTool.hexStr2Bytes(sb.toString());
        tLen[0] = tv.length;
        System.arraycopy(tv,0,dataOut,0,tv.length);

        return 0;
    }

    public int addApp(){
        AidList app = null;
        int iRet = -1;
        //aid1:A0 00 00 00 03 10 10
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41}; ////VISA
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x00, 0x03, 0x10, 0x10};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;


        iRet =mEmvCore.EmvLibAddApp(app);



        //aid2:
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41}; ////VISA
        app.mAidNameLen = 4;

        app.mAidLen = 5;
        app.mAid = new byte[]{(byte) 0xA1, 0x22 , 0x33, 0x44, 0x55};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;


        iRet =mEmvCore.EmvLibAddApp(app);

        //aid3: A000000333010102
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41}; ////VISA
        app.mAidNameLen = 4;

        app.mAidLen = 8;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x03, 0x33, 0x01, 0x01, 0x02};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x01, 0x56};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x01, 0x56};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;


        iRet =mEmvCore.EmvLibAddApp(app);

        //aid4:
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41}; //VISA
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x03, 0x33, 0x01, 0x01};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x01, 0x56};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x01, 0x56};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);

        //aid5
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41}; ////VISA
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x00, 0x04, 0x10, 0x10};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);


        //aid6
        app = new AidList();
        app.mAidName = new byte[]{0x41,0x45}; //AE
        app.mAidNameLen = 4;

        app.mAidLen = 8;
        //A0 00 00 07 90 01 05 02
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x07, (byte) 0x90, 0x01, 0x05,0x02};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);
//        LogUtil.e(TAG,"EmvLibAddApp 6  iRet == " + iRet);


        //aid7
        app = new AidList();
        app.mAidName = new byte[]{0x4D,0x41,0x53,0x54}; //MASTER
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        //A0 00 00 07 90 01 05 02  AE
        //A0 00 00 00 10 88 88  Master
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x00, (byte) 0x10, (byte) 0x88, (byte) 0x88};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);
//        LogUtil.e(TAG,"EmvLibAddApp 7  iRet == " + iRet);


        // A0 00 00 03 33 01 01 01
        //aid8:   调试贵州农信新加的
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41}; //VISA
        app.mAidNameLen = 4;

        app.mAidLen = 8;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x03, 0x33, 0x01, 0x01,0x01};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x01, 0x56};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x01, 0x56};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);



        return iRet;
    }

    public int addCAPubKey(){
        int iRet = 0;
        CAPubKey capk = null;
        capk = new CAPubKey();
        capk.mRID = new byte[]{(byte) 0xA0,0x00,0x00,0x00,0x03};
        capk.mKeyID = 0x50;
        capk.mHashAlgID = 0x01;
        capk.mRsaAlgID = 0x01;
        capk.mModuleLen = (byte) 128;
        capk.mModule = new byte[]{
                (byte) 0xD1,0x11,(byte) 0x97,0x59,0x00,0x57,(byte) 0xB8,0x41,(byte) 0x96,(byte) 0xC2,(byte) 0xF4,(byte) 0xD1,0x1A,(byte) 0x8F,0x3C,0x05,
                0x40,(byte) 0x8F,0x42,0x2A,0x35,(byte) 0xD7,0x02,(byte) 0xF9,0x01,0x06,(byte) 0xEA,0x5B,0x01,(byte) 0x9B,(byte) 0xB2,(byte) 0x8A,
                (byte) 0xE6,0x07,(byte) 0xAA,(byte) 0x9C,(byte) 0xDE,(byte) 0xBC,(byte) 0xD0,(byte) 0xD8,0x1A,0x38,(byte) 0xD4,(byte) 0x8C,0x7E,(byte) 0xBB,0x00,0x62,
                (byte) 0xD2,(byte) 0x87,0x36,(byte) 0x9E,(byte) 0xC0,(byte) 0xC4,0x21,0x24,0x24,0x6A,(byte) 0xC3,0x0D,(byte) 0x80,(byte) 0xCD,0x60,0x2A,
                (byte) 0xB7,0x23,(byte) 0x8D,0x51,0x08,0x4D,(byte) 0xED,0x46,(byte) 0x98,0x16,0x2C,0x59,(byte) 0xD2,0x5E,(byte) 0xAC,0x1E,
                0x66,0x25,0x5B,0x4D,(byte) 0xB2,0x35,0x25,0x26,(byte) 0xEF,0x09,(byte) 0x82,(byte) 0xC3,(byte) 0xB8,(byte) 0xAD,0x3D,0x1C,
                (byte) 0xCE,(byte) 0x85,(byte) 0xB0,0x1D,(byte) 0xB5,0x78,(byte) 0x8E,0x75,(byte) 0xE0,(byte) 0x9F,0x44,(byte) 0xBE,0x73,0x61,0x36,0x6D,
                (byte) 0xEF,(byte) 0x9D,0x1E,0x13,0x17,(byte) 0xB0,0x5E,0x5D,0x0F,(byte) 0xF5,0x29,0x0F,(byte) 0x88,(byte) 0xA0,(byte) 0xDB,0x47
        };
        capk.mExponentLen = 3;
        capk.mExponent = new byte[]{0x01,0x00,0x01};
        capk.mExpiredDate = new byte[]{0x17,0x12,0x31};
        capk.mCheckSum = new byte[]{(byte) 0xB7,0x69,0x77,0x56,0x68,(byte) 0xCA,(byte) 0xCB,0x5D,0x22,(byte) 0xA6,0x47,(byte) 0xD1,(byte) 0xD9,(byte) 0x93,0x14,0x1E,
                (byte) 0xDA,(byte) 0xB7,0x23,0x7B};
        iRet =mEmvCore.EmvLibAddCAPubKey(capk);

        capk = new CAPubKey();
        capk.mRID = new byte[]{(byte) 0xA0,0x00,0x00,0x00,0x03};
        capk.mKeyID = 0x57;
        capk.mHashAlgID = 0x01;
        capk.mRsaAlgID = 0x01;
        capk.mModuleLen = (byte) 96;
        capk.mModule = new byte[]{
                (byte)0x94,(byte)0x2B,(byte)0x7F,(byte)0x2B,(byte)0xA5,(byte)0xEA,(byte)0x30,(byte)0x73,(byte)0x12,(byte)0xB6,(byte)0x3D,(byte)0xF7,(byte)0x7C,(byte)0x52,(byte)0x43,(byte)0x61,
                (byte)0x8A,(byte)0xCC,(byte)0x20,(byte)0x02,(byte)0xBD,(byte)0x7E,(byte)0xCB,(byte)0x74,(byte)0xD8,(byte)0x21,(byte)0xFE,(byte)0x7B,(byte)0xDC,(byte)0x78,(byte)0xBF,(byte)0x28,
                (byte)0xF4,(byte)0x9F,(byte)0x74,(byte)0x19,(byte)0x0A,(byte)0xD9,(byte)0xB2,(byte)0x3B,(byte)0x97,(byte)0x13,(byte)0xB1,(byte)0x40,(byte)0xFF,(byte)0xEC,(byte)0x1F,(byte)0xB4,
                (byte)0x29,(byte)0xD9,(byte)0x3F,(byte)0x56,(byte)0xBD,(byte)0xC7,(byte)0xAD,(byte)0xE4,(byte)0xAC,(byte)0x07,(byte)0x5D,(byte)0x75,(byte)0x53,(byte)0x2C,(byte)0x1E,(byte)0x59,
                (byte)0x0B,(byte)0x21,(byte)0x87,(byte)0x4C,(byte)0x79,(byte)0x52,(byte)0xF2,(byte)0x9B,(byte)0x8C,(byte)0x0F,(byte)0x0C,(byte)0x1C,(byte)0xE3,(byte)0xAE,(byte)0xED,(byte)0xC8,
                (byte)0xDA,(byte)0x25,(byte)0x34,(byte)0x31,(byte)0x23,(byte)0xE7,(byte)0x1D,(byte)0xCF,(byte)0x86,(byte)0xC6,(byte)0x99,(byte)0x8E,(byte)0x15,(byte)0xF7,(byte)0x56,(byte)0xE3
        };
        capk.mExponentLen = 3;
        capk.mExponent = new byte[]{0x01,0x00,0x01};
        capk.mExpiredDate = new byte[]{0x17,0x12,0x31};
        capk.mCheckSum = new byte[]{(byte)0x25,(byte)0x1A,(byte)0x5F,(byte)0x5D,(byte)0xE6,(byte)0x1C,(byte)0xF2,(byte)0x8B,(byte)0x5C,(byte)0x6E,(byte)0x2B,
                (byte)0x58,(byte)0x07,(byte)0xC0,(byte)0x64,(byte)0x4A,(byte)0x01,(byte)0xD4,(byte)0x6F,(byte)0xF5};
        iRet =mEmvCore.EmvLibAddCAPubKey(capk);

        capk = new CAPubKey();
        capk.mRID = new byte[]{(byte)0xA0,0x00,0x00,0x03,0x33};
        capk.mKeyID = (byte) 0xC0;
        capk.mHashAlgID = 0x01;
        capk.mRsaAlgID = 0x01;
        capk.mModuleLen = (byte) 144;
        capk.mModule = new byte[]{
                (byte)0xC7,(byte)0xCD,(byte)0xB6,(byte)0xF2,(byte)0xA3,(byte)0xFE,(byte)0x80,(byte)0xA8,(byte)0x83,(byte)0x4C,(byte)0xDD,(byte)0xDD,(byte)0x32,(byte)0x6E,(byte)0x10,(byte)0x82,
                (byte)0xAA,(byte)0x22,(byte)0x88,(byte)0xF4,(byte)0x7C,(byte)0x46,(byte)0x4D,(byte)0x57,(byte)0xB3,(byte)0x47,(byte)0x18,(byte)0x19,(byte)0x34,(byte)0x31,(byte)0x71,(byte)0x1A,
                (byte)0x44,(byte)0x11,(byte)0x91,(byte)0x48,(byte)0x05,(byte)0x50,(byte)0x44,(byte)0xCF,(byte)0xE3,(byte)0x31,(byte)0x37,(byte)0x08,(byte)0xBE,(byte)0xD0,(byte)0xC9,(byte)0x8E,
                (byte)0x1C,(byte)0x58,(byte)0x9B,(byte)0x0F,(byte)0x53,(byte)0xCF,(byte)0x6D,(byte)0x7E,(byte)0x82,(byte)0x9F,(byte)0xCD,(byte)0x90,(byte)0x6D,(byte)0x21,(byte)0xA9,(byte)0x0F,
                (byte)0xD4,(byte)0xCB,(byte)0x6B,(byte)0xAF,(byte)0x13,(byte)0x11,(byte)0x0C,(byte)0x46,(byte)0x85,(byte)0x10,(byte)0x7C,(byte)0x27,(byte)0xE0,(byte)0x09,(byte)0x81,(byte)0xDB,
                (byte)0x29,(byte)0xDC,(byte)0x0A,(byte)0xC1,(byte)0x86,(byte)0xE6,(byte)0xD7,(byte)0x01,(byte)0x57,(byte)0x7F,(byte)0x23,(byte)0x86,(byte)0x56,(byte)0x26,(byte)0x24,(byte)0x4E,
                (byte)0x1F,(byte)0x9B,(byte)0x2C,(byte)0xD1,(byte)0xDD,(byte)0xFC,(byte)0xB9,(byte)0xE8,(byte)0x99,(byte)0xB4,(byte)0x1F,(byte)0x50,(byte)0x84,(byte)0xD8,(byte)0xCC,(byte)0xC1,
                (byte)0x78,(byte)0xA7,(byte)0xC3,(byte)0xF4,(byte)0x54,(byte)0x6C,(byte)0xF9,(byte)0x31,(byte)0x87,(byte)0x10,(byte)0x6F,(byte)0xAB,(byte)0x05,(byte)0x5A,(byte)0x7A,(byte)0xC6,
                (byte)0x7D,(byte)0xF6,(byte)0x2E,(byte)0x77,(byte)0x8C,(byte)0xB8,(byte)0x88,(byte)0x23,(byte)0xBA,(byte)0x58,(byte)0xCF,(byte)0x75,(byte)0x46,(byte)0xC2,(byte)0xB0,(byte)0x9F
        };
        capk.mExponentLen = 3;
        capk.mExponent = new byte[]{0x01,0x00,0x01};
        capk.mExpiredDate = new byte[]{0x17,0x12,0x31};
        capk.mCheckSum = new byte[]{(byte)0x8B,(byte)0x09,(byte)0x4D,(byte)0x26,(byte)0x0B,(byte)0xDF,(byte)0x8B,(byte)0xFC,(byte)0x8B,(byte)0x9A,(byte)0x88,(byte)0xB0,(byte)0xC1,(byte)0x77,(byte)0xA4,(byte)0x3F,
                (byte)0xE2,(byte)0xFA,(byte)0xE7,(byte)0x65};
        iRet =mEmvCore.EmvLibAddCAPubKey(capk);
        return iRet;
    }

    public void resetModule() {
        financialModule.PowerOff();
        financialModule.init();
        SystemClock.sleep(3000);
        financialModule.flush();
    }

    @Deprecated
    public int AddApp() {

        byte[] AppName = new byte[33];
        byte AidLen = 0;
        byte SelFlag = 0;
        byte Priority = 0;
        byte TargetPer = 0;
        byte MaxTargetPer = 0;
        byte FloorLimitCheck = 1;
        byte RandTransSel = 1;
        byte VelocityCheck = 1;
        int FloorLimit = 2000;
        int Threshold = 0;
        byte[] TACDenial = new byte[6];
        byte[] TACOnline = new byte[6];
        byte[] TACDefault = new byte[6];
        byte[] AcquierId = new byte[7];
        byte[] dDOL = new byte[256];
        byte[] tDOL = new byte[256];
        byte[] Version = new byte[3];
        byte[] RiskManData = new byte[10];

        byte CL_bStatusCheck = 0;
        int CL_FloorLimit = 0;
        int CL_TransLimit = 0;
        int CL_CVMLimit = 0;
        byte TermQuali_byte2 = 0;


        byte[] TACDenial_1 = {(byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00};
        byte[] TACOnline_1 = {(byte) 0xD8, (byte) 0x40, (byte) 0x04, (byte) 0xF8, (byte) 0x00};
        byte[] TACDefault_1 = {(byte) 0xD8, (byte) 0x40, (byte) 0x00, (byte) 0xA8, (byte) 0x00};
        byte[] AcquierId_1 = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x12, (byte) 0x34, (byte) 0x56};
        byte[] dDOL_1 = {(byte) 0x03, (byte) 0x9F, (byte) 0x37, (byte) 0x04};
        byte[] tDOL_1 = {(byte) 0x0F, (byte) 0x9F, (byte) 0x02, (byte) 0x06, (byte) 0x5F, (byte) 0x2A, (byte) 0x02, (byte) 0x9A, (byte) 0x03, (byte) 0x9C, (byte) 0x01, (byte) 0x95, (byte) 0x05, (byte) 0x9F, (byte) 0x37, (byte) 0x04};
        byte[] Version_1 = {(byte) 0x00, (byte) 0x8c};

        System.arraycopy(TACDenial_1, 0, TACDenial, 0, TACDenial_1.length);
        System.arraycopy(TACOnline_1, 0, TACOnline, 0, TACOnline_1.length);
        System.arraycopy(TACDefault_1, 0, TACDefault, 0, TACDefault_1.length);
        System.arraycopy(AcquierId_1, 0, AcquierId, 0, AcquierId_1.length);
        System.arraycopy(dDOL_1, 0, dDOL, 0, dDOL_1.length);
        System.arraycopy(tDOL_1, 0, tDOL, 0, tDOL_1.length);
        System.arraycopy(Version_1, 0, Version, 0, Version_1.length);

        byte[] AID1 = {(byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x33, (byte) 0x01, (byte) 0x1};
        byte[] AID = new byte[17];
        System.arraycopy(AID1, 0, AID, 0, AID1.length);
        AidLen = 7;
        FloorLimitCheck = 1;

        byte[] Version1 = new byte[3];
        byte[] Version2 = {(byte) 0x00, (byte) 0x30};
        System.arraycopy(Version2, 0, Version1, 0, Version2.length);
        byte EC_bTermLimitCheck = 1;
        int EC_TermLimit = 100000;

        EMVAPPLIST PBOC_TEST_APP = new EMVAPPLIST(AppName, AID, AidLen, SelFlag,
                Priority, TargetPer, MaxTargetPer,
                FloorLimitCheck, RandTransSel, VelocityCheck,
                FloorLimit, Threshold, TACDenial,
                TACOnline, TACDefault, AcquierId, dDOL,
                tDOL, Version1, RiskManData, EC_bTermLimitCheck,
                EC_TermLimit, CL_bStatusCheck, CL_FloorLimit, CL_TransLimit,
                CL_CVMLimit, TermQuali_byte2);


        return financialModule.EmvLib_AddApp(PBOC_TEST_APP.toBytes());

    }

    /**
     * 设置EMV
     *
     * @return
     */
    @Deprecated
    public int setEMVParam() {

        EMVParam emvParam = new EMVParam();
        byte[] MerchCateCode = new byte[2];
        MerchCateCode[0] = 0x00;
        MerchCateCode[1] = 0x01;
        emvParam.setMerchCateCode(MerchCateCode);
        String MerchId = "123456789012345";
        emvParam.setMerchId(MerchId.getBytes());
        emvParam.setMerchName("EMV LIBRARY".getBytes());
        emvParam.setTermId("12345678".getBytes());
        emvParam.setTerminalType((byte) 0x22);
        emvParam.setSurportPSESel((byte) 0x01);
        byte[] Capability = {(byte) 0xE0, (byte) 0x60, (byte) 0xC8};
        emvParam.setCapability(Capability);
        byte[] ExCapability = {(byte) 0x60, (byte) 0x00, (byte) 0xF0,
                (byte) 0x20, (byte) 0x01};
        emvParam.setExCapability(ExCapability);
        byte[] CountryCode = {(byte) 0x01, (byte) 0x56};
        byte[] TransCurrCode = {(byte) 0x01, (byte) 0x56};
        byte[] ReferCurrCode = {(byte) 0x01, (byte) 0x56};
        emvParam.setCountryCode(CountryCode);
        emvParam.setTransCurrCode(TransCurrCode);
        emvParam.setTransCurrExp((byte) 0x02);
        emvParam.setReferCurrCode(CountryCode);
        emvParam.setCL_TransLimit(100000);
        emvParam.setTransType((byte) 0x00);// 交易类型
        byte[] TermTransQuali = {0x24, 0x00, 0x00, (byte) 0x80};
        emvParam.setTermTransQuali(TermTransQuali);
        emvParam.setCL_bStatusCheck((byte) 0x00);
        emvParam.setCL_CVMLimit(10000);
        emvParam.setCL_FloorLimit(20000);

        emvParam.setECTSI((byte) 0x01);
        emvParam.setEC_TermLimit(10000);
        emvParam.setEC_bTermLimitCheck((byte) 0x01);
        byte[] params = emvParam.toBytes();
        return financialModule.EmvLib_SetParam(params);

    }

    /**
     * 自动识别卡类型
     */
    @Deprecated
    public void autoReadCardNo() {

        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        Log.e(TAG, "openModule res=" + res);
        if(res==1){
            financialModule.PowerOff();
            SystemClock.sleep(1000);
            financialModule.PowerOn();
            SystemClock.sleep(3000);
            financialModule.EmvLib_Init();
            res = openModule();
        }
        Log.e(TAG, "openModule:" + res);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                        break;
                    }
                }
                SystemClock.sleep(100);
                if (financialModule.libIccCheck((byte) 0x00) == 0) {
                    if (getPan((byte) 0x00)) {
                        break;
                    }
                }
                byte[] cardtype = new byte[2];
                byte[] snbuf = new byte[20];
                if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                    if (getPan((byte) 0x01)) {
                        break;
                    }
                }
                SystemClock.sleep(150);
                if (financialModule.libMcrCheck() == 0) {
                    if (mcrRead()) {
                        break;
                    }
                }
                SystemClock.sleep(150);

            }
        }finally {

//            closeModule();
            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }

    }


    /**
     * 全部打开
     *
     * @return
     */
    public int openModule() {
        int ret = -1;
//        ret = MainActivity.getMainMcr().DLL_McrOpen();
//        SystemClock.sleep(50);
        ret = MainActivity.getmMainPicc().DLL_PiccOpen();
        return ret;
    }

    /**
     * 全部关闭
     */
    public void closeModule() {
        LogUtil.e(TAG,"closeModule=====");
        MainActivity.getMainMcr().DLL_McrClose();
        MainActivity.getmMainIcc().DLL_IccClose((byte) 0x00);
        MainActivity.getmMainPicc().DLL_PiccClose();  // closeModule 关闭
        deliverResult(callback, DeviceInterface.Result.SUCCEED, new Bundle(), isOnMain);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
    }

    /**
     * 打开非接
     *
     * @return
     */
    private Timer openPicc() {
//        int ret = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
//        LogUtil.e(TAG,"PICC DLL_IDOpen ret=" + ret);
        if(Build.MODEL.equals("A108Plus")) {
            LogUtil.e(TAG,"IO转换 IDCReadInterface.gpio_control(100)");
            IDCReadInterface.gpio_control(100,0);
        }
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }

//        int res = -1;
//        byte[] atr = new byte[20];
//        for (int i = 0; i < 3; i++) {
//
//            res = MainActivity.getmMainPicc().DLL_PiccOpen();
//            LogUtil.e(TAG,"DLL_PiccOpen res =" + res);
//            if (res == 0) {
//                break;
//            } else {
//                MainActivity.getmMainPicc().DLL_PiccClose();
//            }
//        }
//        Log.e(TAG, "libPiccOpen:" + res);
//        if (res != 0) {
//            deliverError(ErrorDefine.PICC_OPEN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.PICC_OPEN_ERR));
//            return null;
//        }
        return tm;
    }


    /**
     * 打开磁头
     *
     * @return
     */
    private Timer openMsr() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
//        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        for (int i = 0; i < 3; i++) {
//            res = financialModule.libMcrOpen();
            res = MainActivity.getMainMcr().DLL_McrOpen();
            if (res == 0) {
                break;
            } else {
//                financialModule.libMcrClose();
//                financialModule.PowerOff();
//                SystemClock.sleep(1000);
//                financialModule.PowerOn();
//                SystemClock.sleep(3000);
//                financialModule.EmvLib_Init();
                MainActivity.getMainMcr().DLL_McrClose();
                MainActivity.getMainMcr().DLL_McrReset();
            }
        }
        Log.e(TAG, "LibMcrOpen:" + res);
        if (res != 0) {
            deliverError(ErrorDefine.MSR_OPEN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.MSR_OPEN_ERR));
            return null;
        }
        return tm;

    }
    @Deprecated
    public void readPiccCardNo() {
        Timer tm = openPicc();
        if (tm == null) {
            return;
        }
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.PICC_OPEN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.PICC_OPEN_ERR));
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (getPan((byte) 0x01)) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        financialModule.libPiccClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    @Deprecated
    public void readIcCardNo() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.TIME_OUT, ErrorDefine.getErrorDescribe(ErrorDefine.TIME_OUT));
                    break;
                }
            }
            if (financialModule.libIccCheck((byte) 0x00) == 0) {
                if (getPan((byte) 0x00)) {
                    break;
                }

            }
            SystemClock.sleep(200);
        }
        financialModule.libIccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 获取主张号（卡号）
     *
     * @param cardType
     * @return
     */
    public boolean getPan(byte cardType) {

        byte[] pan = new byte[30];
        int[] len = new int[1];
        if (financialModule.EmvLib_GetPan(cardType, pan, len) == 0) {
            BankCardInfoBean bean = new BankCardInfoBean();
            if (cardType == (byte) 0x00) {
                bean.setCardType(0);
            } else {
                bean.setCardType(2);
            }
            bean.setCardNo(new String(pan, 0, len[0]));
            Bundle bundle = new Bundle();
            bundle.putParcelable("data", bean);
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            return true;
        } else {
            deliverError(ErrorDefine.GET_PAN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_PAN_ERR));
            return false;
        }

    }


    public void readMsr() {
        Timer tm = openMsr();
        if (tm == null) {
            return;
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.MSR_CARD_TIME, ErrorDefine.getErrorDescribe(ErrorDefine.MSR_CARD_TIME));
                    break;
                }
            }
            if (MainActivity.getMainMcr().DLL_McrCheck() == 0) {

                if (mcrRead()) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        MainActivity.getMainMcr().DLL_McrClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    public boolean mcrRead() {
        byte[] track1 = new byte[200];
        byte[] track2 = new byte[200];
        byte[] track3 = new byte[200];
        byte[] len1 = new byte[1];
        byte[] len2 = new byte[1];
        byte[] len3 = new byte[1];
        int result = MainActivity.getMainMcr().DLL_McrRead(len1,track1,len2,track2,len3,track3);
        LogUtil.e(TAG,"读磁条卡result=" + result);
        if (result != 0) {
            String tk1 = new String(track1).trim();
            String tk2 = new String(track2).trim();
//            tk2 = "==112090054101110097089061";  //贵州农信存折数据
            String tk3 = new String(track3).trim();
//            tk3 = "114074101105112090054101109090054088112074113111113054101106109113067099111074105105112053054101109112043103112074097105";
            LogUtil.e(TAG,"读磁条卡tk1= " + tk1);
            LogUtil.e(TAG,"读磁条卡tk2= " + tk2);
            LogUtil.e(TAG,"读磁条卡tk3= " + tk3);

            BankCardInfoBean bean = new BankCardInfoBean();
            bean.cardType = 1;
            String cardNo = decodeCardNo(tk2);
            if (cardNo == null) {
                deliverError(ErrorDefine.SWIPE_ERROR, ErrorDefine.getErrorDescribe(ErrorDefine.SWIPE_ERROR));
                return false;
            }

            bean.setCardNo(cardNo);
            bean.oneMagneticTrack = tk1.trim();
            bean.twoMagneticTrack = tk2.trim();
            bean.threeMagneticTrack = tk3.trim();
            Bundle bundle = new Bundle();
            bundle.putParcelable("data", bean);
            bundle.putInt("slot",0);  // 0 磁条卡  1 插卡  2  非接卡
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            return true;
        } else {
            deliverError(ErrorDefine.SWIPE_ERROR, ErrorDefine.getErrorDescribe(ErrorDefine.SWIPE_ERROR));
            return false;
        }

    }

    /**
     * 从二磁道取卡号
     *
     * @param track
     * @return
     */
    public static String decodeCardNo(String track) {
        int start = 0;
        if (track != null && track.trim().length() > 0) {
            int track2_end = track.indexOf("=");
            if (track2_end == -1) {
                track2_end = track.indexOf("^");
            }
            if (track2_end <= 1) {

                return "";
            }
            for (int i = 0; i < track.length(); i++) {
                if (Character.isDigit(track.charAt(i))) {
                    start = i;
                    break;
                }
            }
            return track.substring(start, track2_end);
        }
        return "";
    }

    /**
     * 从tag57取卡号
     *
     * @param track2
     * @return
     */
    public static String getCardNo(String track2) {
        if (track2 == null)
            return null;
        int sta = 0;
        int end = track2.indexOf("D");
        if (end != -1) {
            String cardno = track2.substring(sta, end);
            return cardno;
        }
        return null;
    }

    /**
     * 生成记录
     *
     * @param log
     * @return
     */
    public static List<LoadLogBean> parseLoadLog(byte[] log) {
        int num = log[0];
        Log.e("num", num + "===");
        List<LoadLogBean> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            try {
                LoadLogBean bean = new LoadLogBean();
                byte[] tmp = new byte[6];
                System.arraycopy(log, 1 + i * 45, tmp, 0, 6);
                bean.setBeforeAmount(ByteTool.byte2hex(tmp));
                System.arraycopy(log, 1 + 6 + i * 45, tmp, 0, 6);
                bean.setAfterAmount(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + i * 45, tmp, 0, 2);
                bean.setTransNo(ByteTool.byteArray2int(tmp));
                tmp = new byte[1];
                System.arraycopy(log, 1 + 6 + 6 + 2 + i * 45, tmp, 0, 1);
                bean.setTransType(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + i * 45, tmp, 0, 2);
                bean.setCountryCode(ByteTool.byte2hex(tmp));

                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + i * 45, tmp, 0, 2);
                bean.setTransCurrCode(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + i * 45, tmp, 0, 3);
                bean.setDate(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + i * 45, tmp, 0, 3);
                bean.setTime(ByteTool.byte2hex(tmp));
                tmp = new byte[20];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + 3 + i * 45, tmp, 0, 20);
                try {
                    bean.setMerchName(new String(tmp, "gbk").trim());
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                list.add(bean);
            } catch (ArrayIndexOutOfBoundsException e) {
                break;
            }

        }
        return list;

    }

    /**
     * 生成记录
     *
     * @param log
     * @return
     */
    public static List<TradeLogBean> parseLog(byte[] log) {
        int num = log[0];
        Log.e("num", num + "===");
        List<TradeLogBean> list = new ArrayList<>();
        //标签对应数据：授权金额6，其他金额6，交易货币代码2，交易类型1，终端国家代码2，应用交易计数器 2,交易日期3，交易时间3，商户名称20，
        int[] tags = new int[]{0x9F02,0x9F03,0x5F2A,0x9C,0x9F1A,0x9F36,0x9A,0x9F21,0x9F4E,};
        int[] dlen = new int[]{6,     6,      2,    1,    2,     2 ,    3,   3,     20,    };
        for (int i = 0; i < num; i++) {
            try {
                TradeLogBean bean = new TradeLogBean();
                byte[] tmp = new byte[6];
                System.arraycopy(log, 1 + i * 45, tmp, 0, 6);
                bean.setAmount(ByteTool.byte2hex(tmp));
                System.arraycopy(log, 1 + 6 + i * 45, tmp, 0, 6);
                bean.setOtherAmount(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + i * 45, tmp, 0, 2);
                bean.setTransNo(ByteTool.byteArray2int(tmp));
                tmp = new byte[1];
                System.arraycopy(log, 1 + 6 + 6 + 2 + i * 45, tmp, 0, 1);
                bean.setTransType(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + i * 45, tmp, 0, 2);
                bean.setCountryCode(ByteTool.byte2hex(tmp));

                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + i * 45, tmp, 0, 2);
                bean.setTransCurrCode(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + i * 45, tmp, 0, 3);
                bean.setDate(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + i * 45, tmp, 0, 3);
                bean.setTime(ByteTool.byte2hex(tmp));
                tmp = new byte[20];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + 3 + i * 45, tmp, 0, 20);
                try {
                    bean.setMerchName(new String(tmp, "gbk").trim());
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                list.add(bean);
            } catch (ArrayIndexOutOfBoundsException e) {
                break;
            }

        }
        return list;

    }

    protected static void deliverResult(final DeviceCallback callback, DeviceInterface.Result result, Bundle bundle, boolean onMainThread) {

        DeviceInterface.deliverResult(callback, result, bundle, onMainThread);

    }

    protected void deliverError(int code, String message) {
        Bundle bundle = new Bundle();
        bundle.putInt("code", code);
        bundle.putString("message", message);
        deliverResult(this.callback, DeviceInterface.Result.ERROR, bundle, this.isOnMain);
    }


}
